想在js方面的水平有更进一步的提升,变量对象,作用域链,闭包,匿名函数,this关键字,原型链,构造器,js预编译,对象模型,执行模型,prototype继承这些概念肯定会经常碰到。
这么多的概念,有点晕了吧。这里抓取几个关键字,讲故事 一样把这些概念给串起来。
首先来看下对象的创建过程和函数对象的创建过程:
对象创建过程:
对象需要通过函数对象来创建。相当于java,c++语言通过类的构造函数创建。这里函数对象充当了类和构造函数的作用。
new Fn(args)的创建过程如下:
1,创建一个built-in object对象obj并初始化;
2,根据Fn.prototype属性的类型给obj的[[prototype]]赋值。如果Fn.prototype为Object类型,则obj的[[prototype]]设置为Fn.prototype,否则为obj的初始化值(Object.prototype)。
3,将obj作为this,使用args参数来调用Fn内部[[call]]方法;
3.1 内部[[call]]方法创建当前执行上下文
3.2 调用Fn的函数体
3.3 销毁当前的执行上下文
3.4 返回Fn的返回值,如果没有返回则返回undefined
4,如果[[call]]的返回值是object,则返回这个值,否则返回obj;
tip:
1,每个对象都有一个隐式的[[prototype]]内部属性,每一个函数对象都有一个显式的prototype属性。
demo:
var Person = function () { }; Person.prototype.Say = function () { alert( "Person say" ); } Person.prototype.Salary = 50000; var Programmer = function () { }; Programmer.prototype = new Person(); Programmer.prototype.WriteCode = function () { alert( "programmer writes code" ); }; Programmer.prototype.Salary = 500; var p = new Programmer(); p.Say(); p.WriteCode(); alert(p.Salary); |
我们来做这样的推导:
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”)的方法。
其余的也都是同样的道理。
函数对象创建过程
无论是在js中自定义函数,还是调用Function创建函数,最终的调用形式都是:var newFun = Function(funcArgs,funcBody);
函数对象的主要创建步骤如下:
1,创建built-in object 对象 fn;
2,将fn的[[prototype]]设置为Function.prototype;
3,设置内部的[[call]]属性;
4,设置内部的[[construct]]属性;
5,设置fn.length为funcArgs.length,如果没有参数,设置为0;
6,使用new Object 同样的逻辑创建一个Object对象fnProto
7,将fnProto.constructor设为fn
8,将fn.prototype设为fnProto
9,返回fn
最后来解析下面几段代码:
1,
var name = 'king_z'; function echo() { alert(name); var name = 'pfzeng'; alert(name); alert(age); } echo();
结果是:
undefined
pfzeng
[脚本出错]
2,
function Foo() {};
var foo = new Foo();
Foo.prototype.label = "laruence";
alert(foo.label); //output: laruence
alert(Foo.label);//output: undefined
参考网站:
[1] http://www.laruence.com/jscss/page/2
[2] http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html
[3] http://www.cnblogs.com/zzcflying/archive/2012/07/20/2601112.html