从面试题学习Javascript 面向对象(创建对象)

  题目:

  

复制代码 代码如下:

  try{

  var me = Man({ fullname: "小红" });

  var she = new Man({ fullname: "小红" });

  console.group();

  console.info("我的名字是:" + me.attr("fullname") + "\n我的性别是:" + me.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小红

  我的性别是:<用户未输入>

  ------------------*/

  me.attr("fullname", "小明");

  me.attr("gender", "男");

  me.fullname = "废柴";

  me.gender = "人妖";

  she.attr("gender", "女");

  console.group();

  console.info("我的名字是:" + me.attr("fullname") + "\n我的性别是:" + me.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小明

  我的性别是:男

  ------------------*/

  console.group();

  console.info("我的名字是:" + she.attr("fullname") + "\n我的性别是:" + she.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小红

  我的性别是:女

  ------------------*/

  me.attr({

  "words-limit": 3,

  "words-emote": "微笑"

  });

  me.words("我喜欢看视频。");

  me.words("我们的办公室太漂亮了。");

  me.words("视频里美女真多!");

  me.words("我平时都看优酷!");

  console.group();

  console.log(me.say());

  /*------[执行结果]------

  小明微笑:"我喜欢看视频。我们的办公室太漂亮了。视频里美女真多!"

  ------------------*/

  me.attr({

  "words-limit": 2,

  "words-emote": "喊"

  });

  console.log(me.say());

  console.groupEnd();

  /*------[执行结果]------

  小明喊:"我喜欢看视频。我们的办公室太漂亮了。"

  ------------------*/

  }catch(e){

  console.error("执行出错,错误信息: " + e);

  }

  知识点:

  (1)JS面向对象基础:ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数”。

  (2)JS创建对象的方法:

  (a)工厂模式:用函数来封装以特定接口创建对象的细节。

      function createPerson(name, age, job){

          var o = new Object();

          o.name = name;

          o.age = age;

          o.job = job;

          o.sayName = function(){

          alert(this.name);

          };

      return o;

      }

    var person1 = createPerson(“Nicholas”, 29, “Software Engineer”);

    var person2 = createPerson(“Greg”, 27, “Doctor”);

    缺点:工厂模式虽然解决了创建多个相识对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。

  (b)构造函数模式:ECMAScript中的构造函数可以用来创建特定类型的对象。可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。

      function Person(name, age, job){

        this.name = name;

        this.age = age;

        this.job = job;

        this.sayName = function(){

        alert(this.name);

        };

      }

      var person1 = new Person(“Nicholas”, 29, “Software Engineer”);

      var person2 = new Person(“Greg”, 27, “Doctor”);

    缺点:使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。不要忘了——ECMAScript中的函数是对象,因此每定义一个函数,

    就是实例化一个对象。

  (c)原型模式:我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型

    的所有实例共享的属性和方法。使用原型对象的好处是可以让所有对象共享它包含的属性和方法

      function Person(){

      }

      Person.prototype.name = “Nicholas”;

      Person.prototype.age = 29;

      Person.prototype.job = “Software Engineer”;

      Person.prototype.sayName = function(){

        alert(this.name);

      };

      var person1 = new Person();

      person1.sayName(); //”Nicholas”

      var person2 = new Person();

      person2.sayName(); //”Nicholas”

      alert(person1.sayName == person2.sayName); //true

    缺点:原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。但是对于引用类型值的属性来说,问题就比较突出了。

    (d)组合使用构造函数模式和原型模式:创建自定义类型的最常见方式,就是使用组合使用构造函数模式和原型模式。构造函数模式用于定义实例属性,

      而原型模式用于定义方法和共享的属性。

      function Person(name, age, job){

        this.name = name;

        this.age = age;

        this.job = job;

        this.friends = [“Shelby”, “Court”];

      }

      Person.prototype = {

        constructor: Person,

        sayName : function () {

        alert(this.name);

        }

      };

      var person1 = new Person(“Nicholas”, 29, “Software Engineer”);

      var person2 = new Person(“Greg”, 27, “Doctor”);

      person1.friends.push(“Van”);

      alert(person1.friends); //”Shelby,Court,Van”

      alert(person2.friends); //”Shelby,Court”

      alert(person1.friends === person2.friends); //false

      alert(person1.sayName === person2.sayName); //true

  答案:

  

复制代码 代码如下:

  <!DOCTYPE html>

  <html>

  <head>

  <style type="text/css" rel="stylesheet">

  </style>

  <title></title>

  </head>

  <body>

  </body>

  <script type="text/javascript">

  window.onload=function()

  {

  var Man;

  //+++++++++++答题区域+++++++++++

  Man=function(obj){

  if(!(this instanceof Man))

  {

  return new Man(obj);

  }

  this.attrObj=obj||{};

  this.wordsObj=[];

  }

  Man.prototype={

  constructor:Man,

  words:function(word){

  word!=undefined&&this.wordsObj.push(word);

  },

  attr:function(attribute,attributeValue)

  {

  var defaultVaule="<用户未输入>";

  if(arguments.length==2){

  this.attrObj[attribute]=attributeValue;

  }

  else if(!(attribute instanceof Object))

  {

  if((this.attrObj[attribute]===undefined))

  {

  return defaultVaule;

  }

  else

  {

  return this.attrObj[attribute];

  }

  }

  else{

  for(property in attribute)

  {

  this.attrObj[property]=attribute[property];

  }

  }

  },

  say:function()

  {

  var limit=this.attrObj['words-limit'],

  outputString,

  wordsLen=this.wordsObj.length;

  outputString=this.attr("fullname")+this.attr("words-emote")+":";

  for(var i=0;i<limit;i++)

  {

  outputString+=this.wordsObj[i];

  }

  return outputString;

  }

  };

  //+++++++++++答题结束+++++++++++

  try{

  var me = Man({ fullname: "小红" });

  var she = new Man({ fullname: "小红" });

  console.group();

  console.info("我的名字是:" + me.attr("fullname") + "\n我的性别是:" + me.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小红

  我的性别是:<用户未输入>

  ------------------*/

  me.attr("fullname", "小明");

  me.attr("gender", "男");

  me.fullname = "废柴";

  me.gender = "人妖";

  she.attr("gender", "女");

  console.group();

  console.info("我的名字是:" + me.attr("fullname") + "\n我的性别是:" + me.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小明

  我的性别是:男

  ------------------*/

  console.group();

  console.info("我的名字是:" + she.attr("fullname") + "\n我的性别是:" + she.attr("gender"));

  console.groupEnd();

  /*------[执行结果]------

  我的名字是:小红

  我的性别是:女

  ------------------*/

  me.attr({

  "words-limit": 3,

  "words-emote": "微笑"

  });

  me.words("我喜欢看视频。");

  me.words("我们的办公室太漂亮了。");

  me.words("视频里美女真多!");

  me.words("我平时都看优酷!");

  console.group();

  console.log(me.say());

  /*------[执行结果]------

  小明微笑:"我喜欢看视频。我们的办公室太漂亮了。视频里美女真多!"

  ------------------*/

  me.attr({

  "words-limit": 2,

  "words-emote": "喊"

  });

  console.log(me.say());

  console.groupEnd();

  /*------[执行结果]------

  小明喊:"我喜欢看视频。我们的办公室太漂亮了。"

  ------------------*/

  }catch(e){

  console.error("执行出错,错误信息: " + e);

  }

  }

  </script>

  </html>