刚学习JavaScript的时候,被告知,JavaScript并不是一门面向对象的语言,而是一门基于对象的语言,也就是万物皆对象.
Prototype:
注:只有函数对象才存在这个属性
这是一个函数对象的属性,用于指向原型对象
他存在的目的好像是多个实例对象共享一个对象的数据,旨在与对象__proto__属性配合,实现继承的效果
__proto__:
对象都拥有这个属性,ES6中箭头函数貌似不存在这个属性
他存在的目的:他就像是一个指针来指向自己构造函数的prototype属性指向的对象,用于寻找自己的继承的属性
我们看一个例子:
假设我们有一个对象obj
我们在使用obj.a时,系统都在做什么
它首先会在obj对象中寻找a属性的属性值,如果找不到就按照obj.__proto__对象是否存在a属性,直到寻找到Object.prototype,因为Object.prototype.__proto__属性指向的对象是null
所以,我们可以得出一个结论:__proto__属性,是一个指针,来指向被” 继承”的对象的,并用于查找属性的.
这里会产生两个问题:
1. 函数对象的prototype属性和对象属性__proto__关系是什么
其实,对于一个函数对象来说,他的prototype属性和他的__proto__属性其实一点关系都没有,但是对于用这个函数产生的对象来说就有和这个函数的prototype属性有关系了,有一个关系就是对象的__proto__属性==函数对象的prototype属性.
例如:
function A(){}//A这个对象拥有prototype属性和__proto__属性 var a=new A();//a这个对象只拥有__proto__属性 a.__proto__==A.prototype//true
从这里就能看出来function对象中的prototype属性只是为了,初始化实例对象的__proto__属性的
一个特殊的函数对象:Function
因为Function对象的构造函数是Function,所以Function对象的__proto__和Function.prototype是一样的
Function.__proto__==Function.prototype//true
2. 为什么,对象的最终属性__proto__都会指向Object.prototype
根据刚才的描述,所有通过new运算符分配出的对象的__proto__属性都是与[function].prototype相等的,
然而一个function被创建时的prototype属性是一个Object对象
验证:
A.prototype.__proto__==Object.prototype//true
而:
a.__proto__==A.prototype//true
于是所有的对象的链头都是Object.prototype
按照上述理论Object.prototype的__proto__的属性应该是Object.prototype
但是,它却是一个特例,指向的是null,为的是,寻找属性时,不造成死循环
我们在这里有一个技巧:
当我们想知道一个对象的__proto__属性到底指的是哪个对象,只要看他是什么类型的对象然后将这个类型对象.prototype返回就是__proto__.(当然,这是天然的__proto__的计算方法,然而__proto__属性是可以被赋值的)
然而,我想问为什么[function].prototype==[obj].__proto__
1. new运算符在做什么
a. 创建一个新的对象,这个对象的类型是object;
b. 设置这个新的对象的内部、可访问性和[[prototype]]属性为构造函数(指prototype.construtor所指向的构造函数)中设置的;
c. 执行构造函数,当this关键字被提及的时候,使用新创建的对象的属性;
d. 返回新创建的对象(除非构造方法中返回的是‘无原型’)。
代码实现:
functioncreatePerson(P) { var o = new Object(); var args =Array.prototype.slice.call(arguments, 1); o.__proto__ = P.prototype; P.prototype.constructor= P; P.apply(o, args); return o; }
2. instanceof在干什么
当我们使用instanceof关键字时,系统在做什么?
我们做个试验(chrome console):
>functionB(){} <undefined >functionC(){}//先创建两个函数对象 <undefined >var c=newC();//创建一个C的实例 <undefined >c instanceofC <true >c instanceofB//显而易见的结果 <false >c.__proto__=B.prototype//我们把原来的继承链修改 <B {} >c instanceofB//结果变成了c是B的实例 <true >c instanceofC//而不是C的实例(目前的继承链càB.prototype) <false >B.prototype.__proto__=C.prototype //(目前的继承链càB.prototypeàC.prototype) <C {} >c instanceofC <true
所以,我们可以看到instanceof的过程就是按照[obj]的继承连在验证[obj].__proto__是否等于[function].prototype
于是我们拿出原来的例子因为Object.prototype.__proto__==null
所以Object.prototypeinstanceof Object 返回的是false
ES6:class
对于ES6的class继承
class B extends A{}
需求有两个:
1. B的实例对象要拥有A的所有属性super
2. B的实例对象继承链要A.prototype B.prototype.__proto__=A.prototype
3. B要有A的静态方法àB.__proto__=A