一、了解创建函数对象时new的过程。 我们先看一段代码:
<script type="text/javascript">
var Person = function () { };
var p = new Person();
</script>
我们可以把new的过程拆分成以下三步:
<1> var p={}; 初始化一个对象p。
<2> p.__proto__=Person.prototype;
<3> Person.call(p);也就是说构造p,也可以称之为初始化p。
二、 此三步的关键点时是第二步,以下为证明材料证明一下:
<script type="text/javascript">
var Person = function() { };
var p = new Person();
alert(p.__proto__ === Person.prototype);
</script>
1、首先,我们先理解下proto是什么?
每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,一直找下去,这也就是我们平时所说的原型链的概念。
2、了解proto属性特点
按照标准,__proto__是不对外公开的,也就是说是个私有属性,但 是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。
3、让我们看一下下面这些代码:
<script type="text/javascript">
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
var p = new Person();
p.Say();
</script>
那就让我们看下为什么p可以访问Person的Say?
首先var p=new Person();可以得出p.proto=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性,于是,他就需要到他的proto中去找,也就是Person.prototype,而我们在上面定义了 Person.prototype.Say=function(){}; 于是,就找到了这个方法。
4、让我们看个更复杂的原型链例子。
<script type"text/javascript">
var Person = function () { };
Person.prototype.Say = function () {
alert("Person say");
}
Person.prototype.Salary =20000;
var Programmer = function () { };
Programmer.prototype = new Person();
Programmer.prototype.WriteCode = function() {
alert("programmer writes code");
};
Programmer.prototype.Salary = 10000;
var p = new Programmer();
p.Say();
p.WriteCode();
alert(p.Salary);
</script>
我们来做这样的推导:
var p=new Programmer()可以得出p.proto=Programmer.prototype;
而在上面我们指定了Programmer.prototype=new Person();
我们来这样拆分,var p1=new Person();Programmer.prototype=p1;
那么:
p1.proto=Person.prototype;
Programmer.prototype.proto=Person.prototype;
根据上面得到p.proto=Programmer.prototype。
可以得到p.proto.proto=Person.prototype。
输出结果分析:
p.Say()。由于p没有Say这个属性,于是去p.proto也就是Programmer.prototype,也就是p1中去找由于p1中也没有Say,那就去p.proto.proto,也就是
Person.prototype中去找,于是就找到了alert(“Person say”)的方法。
其它同理。
三、一幅图说明它们之间的关系
Javascript中12个内置对象,其中10个函数类型,2个对象类型。
上图有十种构造器函数,分别为:date Array Number Object Bloolean String Event Error RegExp Function,这些构造器函数都可以通过new来实例化一个对象
注意:
1、所有构造器的prototype都是对象(object)类型,只有Function.prototype是函数(function)类型,这是为了保证函数构造器们的__proto__指向的都是函数。
2、JSON和Math不是构造器函数,他们是普通的对象。只有构造器函数才能使用new 关键字实例化一个对象,而JSON和Math已经是对象了,所以我们可以不用实例化直接使用JSON和Math中的属性和方法。