前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原型prototype

原型prototype

作者头像
菜的黑人牙膏
发布2019-01-21 16:55:09
5320
发布2019-01-21 16:55:09
举报
文章被收录于专栏:前端学习归纳总结

在Js中,当试图引用对象的某个属性时,会进行GET操作,第一步会检查对象本身是否拥有这个属性,如果有的话就使用它,否则就会往对象的原型链上查询,一直查到该属性或者到达原型链的最顶端(与作用域类似,作用域查询变量,原形链查询属性)。如下代码:

代码语言:javascript
复制
 var anotherObject = {a:2};

   var myObject = Object.create(anotherObject);

   console.log(myObject.a);  //2

myObject本身是没有a属性的,但是它关联到了anotherObject,anotherObject.prototype即作为它的上层原型。

注:使用(for..in)遍历对象时,原理和查找原型链类似,任何可以在原型链中找到的属性并且是可枚举的都会被枚举,如下

代码语言:javascript
复制
  var anotherObject = {a:2};

  var myObject = Object.create(anotherObject);

  for(k in myObject){

   console.log(k); //2

}

所有普通的原型链最终都会指向内置的Object.prototype.

在JS原型链中,假设对myObject.a进行赋值操作,如 myObject.a = 3; 通常情况下,我们会认为myObject会新创建一个a属性,并遮蔽上层的anotherObject.a,使得下次访问myObject.a的值时是为3,但事实并非如此,当我们进行这种操作时,引擎会根据三种情况进行不同工作。

   1.当myObject的上层原型链(本例子即为anotherObject.prototype)中的a属性是只读的(即writable = false),该语句会被忽略(如果在严格模式下,即会抛出一个错误);

   2.当myObject的上层原型链(本例子即为anotherObject.prototype)中的a属性是一个setter,即myObject.a=3的实质是对anotherObject.prototype.a =3的相同操作,不会为myObject新建一个属性。

   3.当myObject的上层原型链(本例子即为anotherObject.prototype)中的a属性是一个普通属性,并且不是只读的,则会进行上述遮蔽操作。

如果想在第一种和第二种情况下进行遮蔽操作,那应该使用Object.defineProperty(...),而不是使用=符号赋值。

Js中并没有像面向类语言一样的复制机制,Js没有实质的类,不能复制多个实例,只能创建多个对象,并且他们的原型都会关联到同一个对象,如下代码:

代码语言:javascript
复制
 function foo(){

   ...

};

  var a = new foo();

  var b = new foo();

  Object.getPrototypeOf(a) === foo.prototype //(true)

 Object.getPrototypeOf(b) === foo.prototype //(true)

实际上,new操作带来的对象关联只是一个副作用,他的实际上调用foo函数,比较好的关联操作应该是选择Object.create(...)(下面介绍),而且new操作会带来一些误解,会让人误以为foo是一个类,并且有一个奇怪的constructor构造属性,如a.construtor === foo (true) ,foo.prototype.construtor === foo(true);实际上a本身并没有construtor这个属性,它是在找不到的时候往上一层查询在foo.prototype中找到。

举例来说,foo.prototype的construtor属性只是foo函数声明的时候的默认属性,与a是没有任何关系的,如果你创建了一个新对象代替foo.prototype,那么新对象不会自动获取该属性,如下

代码语言:javascript
复制
function foo(){

};

  foo.prototype = {...};

 var a  = new foo();

  a.construtor === foo; //false

  a.construtor === Object; //true

这是一种委托行为。a并没有construtor属性,所以他会委托给原型链上的foo.prototype,但是这个对象也没有这个属性,foo,prototype就会再委托给他的原型链上的Object.prototype,并在Object.prototype对象中找到这个属性。

Js最好的继承机制应该是Object.create(...),如下:

代码语言:javascript
复制
 function foo(){

   ...

};

  var a = Object.create(foo.prototype);

调用Object.create函数会创建一个新对象,并把新对象的原型链关联到你指定的对象(本例子中为foo,prototype).

注意,下面是两种常见的错误操作:

   1.bar.prototype = foo.prototype;(和想要的机制不一样,是引用,而不是委托)

   2.var bar.prototype = new foo();(会产生一些副作用,如foo会被执行,可能与预期结果不一样)

另外,在E5之前是没有Obect.create函数的,可以采用以下代码:

代码语言:javascript
复制
 if(!Object.create){

    Object.create = function(o){

       function F(){};

       F.prototype = o;

       return new F();

}

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-02-14 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档