js中原型和实例

  虽然可以通过对象实例访问保存在原型中的值,但却不能通过对象实例重写原型中的值。如果我们
在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那我们就在实例中创建该属性,该
属性将会屏蔽原型中的那个属性。

  如下例子:

  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();

  var person2 = new Person(); 

  person1.name = "Greg";
  alert(person1.name); //"Greg"——来自实例
  alert(person2.name); //"Nicholas"——来自原型

  在这个例子中,person1 的 name 被一个新值给屏蔽了。但无论访问 person1.name 还是访问person2.name 都能够正常地返回值,即分别是"Greg"(来自对象实例)和"Nicholas"(来自原型)。当在 alert()中访问 person1.name 时,需要读取它的值,因此就会在这个实例上搜索一个名为 name的属性。这个属性确实存在,于是就返回它的值而不必再搜索原型了。当以同样的方式访问 person2. name 时,并没有在实例上发现该属性,因此就会继续搜索原型,结果在那里找到了 name 属性。

  当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性;换句话说,添加这个属性只会阻止我们访问原型中的那个属性,但不会修改那个属性。即使将这个属性设置为null,也只会在实例中设置这个属性,而不会恢复其指向原型的链接。不过,使用delete操作符则可以完全删除实例属性,从而让我们能够重新访问原型中的属性。如下所示:

  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();
  var person2 = new Person();
  person1.name = "Greg";
  alert(person1.name); //"Greg"——来自实例
  alert(person2.name); //"Nicholas"——来自原型
  delete person1.name;
  alert(person1.name); //"Nicholas"——来自原型

  在这个修改后的例子中,我们使用 delete 操作符删除了 person1.name,之前它保存的"Greg"值屏蔽了同名的原型属性。把它删除以后,就恢复了对原型中 name 属性的连接。因此,接下来再调用person1.name 时,返回的就是原型中 name 属性的值了。

  使用 hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法(不要忘了它是从 Object 继承来的)只在给定属性存在于对象实例中时,才会返回 true。

  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();
  var person2 = new Person();
  alert(person1.hasOwnProperty("name")); //false
  person1.name = "Greg";
  alert(person1.name); //"Greg"——来自实例
  alert(person1.hasOwnProperty("name")); //true
  alert(person2.name); //"Nicholas"——来自原型
  alert(person2.hasOwnProperty("name")); //false
  delete person1.name;
  alert(person1.name); //"Nicholas"——来自原型
  alert(person1.hasOwnProperty("name")); //false

  通过使用 hasOwnProperty()方法,什么时候访问的是实例属性,什么时候访问的是原型属性就一清二楚了。调用 person1.hasOwnProperty( "name")时,只有当 person1 重写 name 属性后才会返回 true,因为只有这时候 name 才是一个实例属性,而非原型属性。

 

  前面例子中每添加一个属性和方法就要敲一遍 Person.prototype。为减少不必要的输入,也为了从视觉上更好地封装原型的功能,更常见的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象,如下面的例子所示。

  function Person(){ 

  }
  Person.prototype = {
    name : "Nicholas",
    age : 29,
    job: "Software Engineer",
    sayName : function () {
      alert(this.name);
    }
  };

  

 

posted @ 2017-10-15 18:30  清源如风  阅读(3883)  评论(0编辑  收藏  举报