1 背景介绍
1.1什么是原型
学习原型链之前我们首先要明白什么是原型;那么什么是原型呢?我们来简单学习一下:
只要我们像这样简单的定义一个函数foo(),就可以访问像访问其他对象一样访问该函数的属性:
>>>function foo(a,b){return a*b;}
>>>foo.length
2
>>>foo.constructor
Function()
其实我们在创建一个函数的时候,这个函数就包括了prototype属性,它的初始值是一个空对象(object),
>>>typeof foo.prototype
"object"
所以我们可以自己在这个空对象中添加属性,像这样:
>>>foo.prototype = {}
1.2 原型有什么作用
简述一下prototype属性的出现:
第一版浏览器无用户交互—》需要脚本语言—》借鉴C++和Java语言,又想节省服务器资源和时间—》prototype。
由于所有的实例对象共享同一个prototype对象,那么从外界看起来,prototype对象就好像是实例对象的原型,而实例对象则好像"继承"了prototype对象一样。
这个属性包含一个对象(以下简称"prototype对象"),所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。
而实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分成两种,一种是本地的,另一种是引用的。
2 知识剖析
2.1 原型链是什么
我们上面说到,每个构造函数在创建时都包含一个属性prototype,其初始值是一个空对象;
原型链(图片来源与网络)
原型对象结构:
Function.prototype={
constructor :Function,
__proto__:parentprototype,
someprototypeproperties: ...
};
函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针__proto__,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用__proto__一直指向Object的原型对象上,而Object的原型对象用Object.prototype.__proto__ = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。
3 常见问题
Array.isArray(Array.prototype)输出什么?
4 解决方案
Array.prototype是Array构造函数实例的原型,构造函数实例化后仍为数组,所以输出true。
5 编码实战
6 扩展思考
7 参考文献
8 更多讨论
Q1: prototype与_proto_是什么关系?
__proto__(隐式原型)、prototype(显式原型)
A1: 显式原型 explicit prototype property:每一个函数在创建之后都会拥有一个名为prototype的属性,这个属性指向函数的原型对象。
隐式原型 implicit prototype link:JavaScript中任意对象都有一个内置属性[[prototype]],在ES5之前没有标准的方法访问这个内置属性,但是大多数浏览器都支持通过__proto__来访问。ES5中有了对于这个内置属性标准的Get方法Object.getPrototypeOf().
Q2:若想访问一个对象的原型,应该使用什么方法?
获取实例对象obj的原型对象,有三种方法
1. obj.__proto__
2. obj.constructor.prototype
3. Object.getPrototypeOf(obj)
上面三种方法之中,前两种都不是很可靠。最新的ES6标准规定,__proto__属性只有浏览器才需要部署,其他环境可以不部署。而obj.constructor.prototype在手动改变原型对象时,可能会失效。
二者的关系:
隐式原型指向创建这个对象的函数(constructor)的prototype
Q2:在IE中可以使用_proto_属性吗?
A:_proto_将在ES6中进行标准化,目前在ES6的草案附录B中。
Q3:_proto_的兼容性怎么样?
A:_proto_目前是浏览器的内置属性,不同的浏览器有不同的情况。
Q3:new function 和 new object 的差别?
A3:JS之中没有new fuction,我的理解是通过构造函数实例化一个对象?
new Object()就是通过Objec()t这个函数产生的,它会继承Object的所有东西;
同样的,通过构造函数new出来(实例化)的,会继承构造函数里面的属性和方法。js的new关键字传承的机制,这点倒是和其他语言差不多。