JavaScript基础知识(一) Prototype Chain
前些天学习《JavaScript设计模式》(这是一本非常好的书,翻译这本书的作者也很负责,翻译的很好)。其中在介绍JavaScript中如何模拟接口,如何模拟面向对象中的类做了很详尽的解释。但是在学习途中遇到了很多基础知识没有理解,准备用几个章节介绍这些天对这些基础知识学习。最难懂荷花时间最长的就是对JavaScript中Prototype的理解。手头有我从网上搜集的各种资料,在这里贴出百度云的链接,希望想学习的朋友下载学习下。我都整理成PDF格式了。
-
链接:http://pan.baidu.com/share/link?shareid=3816985477&uk=2869009987 密码:dwh4
在介绍Prototype之前先说一个背景知识,ECMA-262-3是javascript的一个规范,各个浏览器厂商都是根据这个ECMA规范定制的javascript功能。ECMAScript就是实现了ECMA-262-3协议的javascript。也就是我们通常所说的javascript。
在这一个章节中,我将总结有关Prototype Chain,对象是如何创建出来的以及Function于Object的关系等基础知识。
文中使用的是V8引擎的Nodejs调试的,如果没有学习过node的同学,可以直接嵌套在HTML中,使用aler()方法查看输出,需要指出的是,__proto__在火狐浏览器种才能调用,其他的调用会出错的。
在讲Prototype之前得先说一下背景知识:
Object
Object.prototype是所有对象的祖先(规则一),Object是Javascript的内置函数。在Javascript中,所有的对象都是字典型结构,也就是说,不管对象多么复杂,都可以用JSON来创建并复制。
-
//创建一个没有属性的对象
-
var obj = {};
-
//创建一个有属性的对象
-
var obj_1 = {name:"angle",age:18,married:false};
-
//创建有属性,有方法的对象
-
var obj_2 = {text:"Hello World",say:function(){console.log(this.text)}}
Function
Function.prototype是所有函数的原型(规则二),包括构造函数。同Object一样,都是javascript的内置函数。在Javascript中的代码只有function一种形式,我们在写一个function test(){}的时候,只不过是建立了一个function类型的实体。
-
function Abd(){
-
this.a = 1;
-
}
-
console.log(typeof Abd);
输出结果 function。
所有的function都有显示的原型和隐性的原型,即__proto__和prototype
Prototype
在Javascript中有两种形式的原型,一种是隐性的原型 __proto__,另一种是显性的原型 Prototype。我们自定义的方法,
但是对象只存在隐性原型:
-
function Abd(){
-
this.a = 1;
-
}
-
var a1 = new Abd();
-
console.log(a1.prototype);
输出结果是:undefined
在javascript中,new关键字创建对象的过程
1à建立一个新的对象。
2à将对象内置的原型对象(__proto__)指向其构造函数的Prototype
3à将该对象作为this参数调用构造函数,完成成员变量等的初始化工作
在第二步中表明了,所有对象的__proto__都指向了其构造函数的Prototype(规则三),即ABd.prototype
其实在第三部中隐含了一个过程。即所有对象的constructor都指向当前对象的构造函数
-
console.log(a1.constructor === Abd);//输出结果为true
然而每一个函数(function类型)都有一个默认属性,即prototype,这个prototype.constructor指向这个函数(规则四)。看似绕了一个圈圈。
基本的知识已经介绍完了,我们使用《nodejs开发指南中》讲原型链中的例子,结合图片理解:
-
function Foo(){
-
}
-
var obj = new Object();
-
var foo = new Foo();
途中虽然交替穿插着很多箭头,看起来很杂乱,其实只不过是根据上面所说的四条规则索引而已
à上图中1处为构造出来的对象。他只有隐性的原型,并且原型指向其构造函数的Prototype
à图中2出可以这么理解,因为function的原型指向的是一个对象,所以这里2处其实就是Foo.prototype。并且Foo.prototype的构造函数constructor指向Foo。同理Foo的__proto__指向其构造函数的原型Function.prototype。因为所有的函数都是Function类型的,Function.prototype的构造函数指向Function(规则三于规则四)
àObject也是一函数。这里就要注意一下了。Object.prototype是没有原型的,所以也是上面的规则一。
à从图中4出可以看出,所有的函数的原型的根都是Function.prototype。这一点符合规则二
Prototype Chain
所谓prototype chain(原型链),从上图中可以看出各种杂乱的箭头指向。原型链就是根据Prototype指向的连接。Javascript中对象的继承使用的就是prototype。当然想要使用javascript实现继承还需要做很多包装。这里只是简单的说明原型链的工作原理:
-
function Sub(){
-
this.a = "haha";
-
this.b = 5;
-
}
-
Sub.prototype.c = function(){//往Sub的原型中添加方法c
-
console.log("prototype method");
-
};
-
Sub.prototype.d = 6;//往Sub的原型中添加属性d
-
var testSub = new Sub();
-
console.log(testSub.a);
-
console.log(testSub.b);
-
testSub.c();
-
console.log(testSub.d);
输出结果:
从结果中可以看出,Sub中并没有定义属性c于d,而是在Sub的原型中定义。从这里可以知道,当function中没有定义先关属性的时候,会从其prototype中寻找,直到找到object.prototype为止。从而形成了一条链条。即为prototype chain。
下面对属性修改的时候原型链是怎么工作的。
-
function Sub(){
-
this.a = "haha";
-
this.b = 5;
-
}
-
Sub.prototype.a = function(){
-
console.log("prototype method");
-
};
-
Sub.prototype.b = 6;
-
Sub.prototype.c = 6;
-
var testSub = new Sub();
-
testSub.a = "hello";
-
testSub.b = 100;
-
testSub.c = 100;
-
console.log(testSub.a);
-
console.log(testSub.b);
-
console.log(testSub.c);
-
console.log(Sub.prototype.c);
结果输出:
在代码的第13行中,设置属性c,从结果来看,并没有把Sub中prototype的属性c设置成100.而是在Sub中添加了一个属性c。这是javascript的特性,可以动态的给对象添加属性。在设置属性的值时,如果没有这个属性,不会从原型链中向上追溯,而是直接在对象中添加相应的属性。有点多态的意思。
当然我所写的这些笔记只是比较浅显的知识,方便回忆。更细致的东西在我分享的那几篇文档中,有兴趣的同学可以下载下来学习交流!
posted on 2013-09-20 22:56 wenlonghor 阅读(696) 评论(0) 编辑 收藏 举报