对于JavaScript prototype的理解

对于事物的理解,往往需要涵盖三个方面:它是什么样子的?它为何会出现?它的外延是什么?理解了内涵与外延才算真正的掌握。

一、原型是什么

以对象a为例,a内部除了固有的属性外,还有一个隐藏的链接指向另一个对象b,这个b就叫作a的原型(也叫原型对象);同时b也有隐藏链接指向c,以此类推,最终指向的是Object.prototype,以上也解释了什么是原型链。可以通过Object.getPrototypeOf(a)来获取a对象的原型。

1.1 令人困惑的prototype

原型之所以使人困惑是因为人们往往把它和prototype属性混在一起,其实这是命名上的失败,对象的原型不是它的属性,而是它的特性。为了方便说明,我将对象的原型称为“原型”使之区别于prototype属性,但两者之间又是紧密相连的。(每个JavaScript对象都有个__proto__属性指向对象的原型,不过__proto__是在ECMAScript 2015中被新加入的属性,而该属性的使用也存在争议)。

1.2 prototype属性

每个JavaScript方法都有一个prototype属性;当你定义一个方法var A = function() {}时,实际上它等价于以下代码:

function A() {
}

// obj是一个新对象,且obj.constructor = A,obj的原型为Object.prototype
A.prototype = obj;

也就是说,当你创建了一个方法的同时,JavaScript会创建一个新对象赋值给方法的prototype属性,并将新对象的constructor指向方法A,如下图所示:

"方法定义过程"
"方法定义过程"

1.2.1 Object.prototype

前面已经说过每个JavaScript方法都有一个prototype属性,所以Object也是一个方法,从使用角度看是一个构造方法。Object.prototype是所有JavaScript对象原型链的最末端(除特殊情况:人为的将原型设置为null)。此外需要说明的是:从JavaScript的语法角度看,并没有构造方法的定义,人们只是根据用途将某些方法称为构造方法,本质上构造方法与一般的方法并没有区别。

二、原型的应用

2.1 被人们忽视的原型

如果你一直从事轻前端重后端的web项目,一直在编写意大利面条式的代码,且这种代码还能满足开发与维护的需求,你确实不需要了解原型。当你发觉JavaScript的代码量在项目中急速增长,代码逐渐变的难以阅读、难以维护时,你开始寻找能避免代码重复的方案,首先你想到的应该是---继承。JavaScript通过原型可以达到这个目的。

2.2 原型的特性

原型最基本的作用就是用来检索对象的属性,当检索某个对象的属性时,首先会检索对象本身的属性,如果本身没有该属性,就去检索对象的原型是否存在该属性,如果仍旧没有找到,就去检索原型的原型,以此类推,沿着原型链一路检索,直到原型链的最后一环Object.prototype,如果最终还是没有找到,就会返回undefined。

2.3 创建对象

在JavaScript中创建对象有以下三种方式:

  • var a = {};
  • var a = Object.create(b);
  • var a = new A();

很显然只有第三种方式才符合OOP的思想,因为它体现了class(类)的概念。在JavaScript的语法层次是没有class的定义的,但是可以通过function来模拟class的行为,通过原型来实现继承。

2.4 JavaScript中的“class”

JavaScript通过function来模拟class,示例代码如下:

var A = function(name, age) {

    // init property 
    this.name = name;
    this.age = age;
    
    // default property 
    this.attr = "attr";
    
    // default function
    this.fun = function() {
    };
};

var a1 = new A("li", 20);
var a2 = new A("zhang", 21);

通过new操作符,对象a1、a2就拥有了A方法中this所拥有的属性和方法。

2.5 JavaScript中的继承

JavaScript是通过原型来实现继承的,示例代码如下:

// define Parent class  
var Parent = function() {
    this.pName = "li";
    this.pFun = function() {
        console.log("parent's fun");
    };
};

// define Child class
var Child = function() {
    this.cName = "xiaoli";
    this.cFun = function() {
        console.log("child's fun");
    };
};

// Child inherit Parent
Child.prototype = new Parent();

// create an object of Child
var c = new Child();

// print: parent's fun
c.pFun();

new操作的内存分析:

  1. 当执行var c = new Child();时,首先新建了一个空对象

    "内存分析-1"
    "内存分析-1"
  2. 将Child方法中的this指向新对象,通过this进行对象初始化

    "内存分析-2"
    "内存分析-2"
  3. 将Child的prototype属性(new Parent())作为新对象的原型

    "内存分析-3"
    "内存分析-3"

2.6 prototype-based(基于原型)的继承 VS class-based(基于类)的继承

class-based语言中,同一个类产生的多个对象之间相互独立、互不干扰;而prototype-based语言中同一个“类”产生的多个对象通过原型捆绑在一起,代码示例如下:

var A = function() {
};
A.prototype = {x : 1};

var a1 = new A();
var a2 = new A();

// change prototype object
A.prototype.x = 2;

// print: 2
console.log(a1.x);

// print: 2
console.log(a2.x);

因为a1、a2的原型为同一个对象,所以当改变原型对象时,a1、a2都受影响;这个例子同时展示了JavaScript作为动态语言的灵活性,在运行时改变“类”的结构,使通过该类产生的对象均受影响。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容