你不知道的javascript之原型prototype(入门级)

Prototype

Prototype是Javascript对象内置的一个特殊属性,这个属性其实就是对其他对象的引用。当你试图访问一个对象的某个属性时,会触发[[get]]操作,先在该对象里检查属性是否存在,存在的话就可以交差了,如果不存在,[[get]]会继续访问该对象的prototype链,检查prototype链中的对象中是不是存在要访问的属性。如果prototype链都检查完了直到Object.prototype还没有找到,那只能返回个undefined,让你另请高明了。下面看个小李子:

var obj = {
    a:2
};
var myobj = Object.create(obj);
myobj.a;//2

上面,obj是个对象,myobj是一个通过Object.create()关联到obj的对象,当使用myobj.a访问属性a时,在对象obj里没有属性a(为什么没有属性a?),就会去检查prototype链中的obj,这才找到属性a

属性设置和屏蔽

既然有prototype机制存在,那对一个对象的属性赋值是怎么样的呢?例如下面这条语句:

obj.attr = 2;

首先会去检查attr属性,如果属性attr在包含在对象obj中,那么会直接进行赋值操作,如果不在对象obj中,就会开始检查prototype链,prototype链中如果存在普通数据访问属性attr(未被标记为只读,如果标记为只读,会报错),就会在对象obj中新建属性attr并赋值2,就屏蔽了prototype链中的属性attr

类?不存在的! JS中只有对象

js中其实是不存在类的,但是却存在一些模仿类的语法,像下面:

function Foo(){
  //todo
} 
var foo = new Foo();

像这种怎么解释呢?Foo不是类吗?都用new了?
在面向类的语言中,实例化一个类会把类的属性和方法复制到实例中,而javascript中并不存在这样的复制机制。这里的new很容易让我们联想到一些语言中也存在的关键字new,通过调用类的构建函数constructor创建实例。
其实new Foo();语句只是新建了对象foo,期间给foo一个内部的prototype链接,关联到Foo.prototype指向的对象。new在两个对象之间建立了关联(Object.create()也可以)。这样一个对象就可以通过这种关联委托访问到另一个对象的属性和函数。那对象foo是怎么创建的呢?同样对象foo的构造函数constructor也委托到prototype链上,但对象Foo里也找不到constructor,这样沿着prototype链找到了顶端的 Object.constructor。例证如下,考虑下面代码和运行截图:

function Foo() { 
    //todo
 }
Foo.prototype = {
     //todo
}; // 创建一个新原型对象
var a1 = new Foo();

你不知道的javascript之原型prototype(入门级)_第1张图片
Paste_Image.png

可见,对象 foo的构造函数委托到了 Object.constructor。至此,你所看到的javascript中的“类”都是假象,是的,就像《百年孤独》里说的那样,“一切都是假的”。

new还是Object.create()

Prototype机制就是存在于对象中的一个内部链接,它会引用其他对象。
通常来说,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在Prototype关联的对象上进行查找。同理,如果在后者中也没有找到需要的引用就会继续查找它的Prototype,以此类推。这一系列对象的链接被称为“原型链”。

既然newObject.create()都可以创建这种关联,两者之间区别何在呢?主要区别是使用new时会生成.prototype.constructor的引用,相比之下,Object.create()就纯粹的多,只是凭空创建一个新的对象并简历关联。
这篇入门级的读书笔记就先写到这里,如有错误,恳请指正,溜了溜了...

你可能感兴趣的:(你不知道的javascript之原型prototype(入门级))