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();
可见,对象
foo
的构造函数委托到了Object.constructor
。至此,你所看到的javascript中的“类”都是假象,是的,就像《百年孤独》里说的那样,“一切都是假的”。
new
还是Object.create()
?
Prototype机制就是存在于对象中的一个内部链接,它会引用其他对象。
通常来说,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在Prototype关联的对象上进行查找。同理,如果在后者中也没有找到需要的引用就会继续查找它的Prototype,以此类推。这一系列对象的链接被称为“原型链”。
既然new
和Object.create()
都可以创建这种关联,两者之间区别何在呢?主要区别是使用new
时会生成.prototype
和.constructor
的引用,相比之下,Object.create()
就纯粹的多,只是凭空创建一个新的对象并简历关联。
这篇入门级的读书笔记就先写到这里,如有错误,恳请指正,溜了溜了...