JavaScript原型和继承原型和继承
前几天看了《再谈js面向对象编程》,当时就请教哈大神,发现文章有的地方可能会造成误导(或者说和ECMA有出入),后
来自己翻一翻ECMA,总算找到“标准”的理解……
本文适合初学者,特别是对构造函数、原型和原型链概念比较模糊的,大牛请路过,好了,让我们一步步来看看js的原型
(链)到底有多神秘……
一、函数创建过程
在了解原型链之前我们先来看看一个函数在创建过程中做了哪些事情,举一个空函数的例子:
function A() {}; 当我们在代码里面声明这么一个空函数,js解析的本质是(肤浅理解有待深入):
1、创建一个对象(有constructor属性及[[Prototype]]属性),根据ECMA,其中[[Prototype]]属性不可见、不可枚举
2、创建一个函数(有name、prototype属性),再通过prototype属性 引用 刚才创建的对象
3、创建变量A,同时把函数的 引用 赋值给变量A
如下图所示:
(注意图中都是“ 引用 ”类型)
每个函数的创建都经历上述过程。
二、构造函数
那么什么是构造函数呢?
按照ECMA的定义
Constructor is a function that creates and initializes the newly created object.
构造函数是用来新建同时初始化一个新对象的函数。
什么样的函数可以用来创建同时初始化新对象呢?答案是:任何一个函数,包括空函数。
所以,结论是:任何一个函数都可以是构造函数。
三、原型
根据前面空函数的创建图示,我们知道每个函数在创建的时候都自动添加了prototype属性,这就是函数的原型,从图中可知
其实质就是对一个对象的引用(这个对象暂且取名原型对象)。
我们可以对函数的原型对象进行操作,和普通的对象无异!一起来证实一下。
围绕刚才创建的空函数,这次给空函数增加一些代码:
function A() {
this.width = 10;
this.data = [1,2,3];
this.key = "this is A";
}
A._objectNum = 0;//定义A的属性
A.prototype.say = function(){//给A的原型对象添加属性
alert("hello world")
}
第7~9行代码就是给函数的原型对象增加一个say属性并引用一个匿名函数,根据“函数创建”过程,图解如下: