js原型鏈與js繼承解析
最近在網上看了諸多js原型鏈的解析,說得雲裡霧裡,不明所以。徹底了解後,決定出個博客記錄一下,一是方便後來人學習,二是方便日後複習。
首先,我們來看一下構造函數、原型、實例之間的關係圖:

所以,我們通常所說的原型鏈,其實指的就是 prototype 的鏈路,因為構造函數和實例是沒有任何指向父節點的成員的。
我們先來看一下 Array 的原型鏈:


三個節點分別是:
Array.prototype --> 有 concat, fill, find 等成員。
Object.prototype -->
null -> 結束。
好了,那麼我們來實現一下自己的原型鏈。
var People = function () {
};
People.prototype.ff = function () {
console.log('People.prototype.f');
};
const Man = function () {
}
Man.prototype = Object.create(People.prototype); // -------------->關聯起來, 注意是從People.prototype創建的
Man.prototype.constructor = Man; // 構造函數,上圖上已經明確constructor要指向自己的構造函數。但是我們是從People.prototype創建的,
// 而Object.create並不會創建constructor, 需要我們去賦值。
const m = new Man();
m.ff();
第10行進行關聯,使用 Man 創建 m 實例,可以找到 ff 函數。
如果沒有第10行進行關聯,則會找不到 ff 函數。
需要注意的是,我們使用 Object.create 進行創建,這個稍候再討論。
雖然我們實現了原型鏈,但是成員變量property我們並沒有作處理,比如上面的代碼,如果在People中添加一個成員,在Man中是找不到的。
如下代碼:
var People = function () {
this.p1 = 2;
};
People.prototype.ff = function () {
console.log('People.prototype.f');
};
const Man = function () {
this.m1 = 2;
}
Man.prototype = Object.create(People.prototype);
Man.prototype.constructor = Man;
const m = new Man();
m.ff();
console.log(m);
打印出來的結果:

m 只包含自己的m1成員。
這個時候,我們需要從People繼承它的property. 具體實現就是在Man的構造函數中,使用People.call(this)。代碼如下:
var People = function () {
this.p1 = 2;
};
People.prototype.ff = function () {
console.log('People.prototype.f');
};
const Man = function () {
People.call(this);
this.m1 = 2;
}
Man.prototype = Object.create(People.prototype);
Man.prototype.constructor = Man;
const m = new Man();
m.ff();
console.log(m);
打印出來的結果:

我們發現p1、m1都包含了。
這也說明了,成員函數的繼承,其實是包含的關係,它並不像原型鏈一樣各自含有各自的東東。
People.call(this)這句代碼,已經明確說明執行People的構造函數,而People使用的this就變成Man的this了。
講到這裡,那麼繼承的實現也就很清晰了:
1、繼承基類的成員變量。
2、將原型鏈連起來。
補充說明:
Object.create. Javascript | MDN 的解釋:
Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
則相當於:
function create(obj) {
function F(){};
F.__proto__ = obj; //以传入参数为原型构造对象
return new F();
}
注意我們創建的代碼:
Man.prototype = Object.create(People.prototype);
Man.prototype.constructor = Man;
相當於 Man.prototype.__proto__ = People.prototype; ---> 指向父節點。
所以這條鏈路就連起來了。
const m = new Man()
這個相當於:
var o = new Object();
o.__proto__ = Man.prototype;
Man.call(o);
了解原理後,我們就了解爲什麼有些人寫:
Man.prototype = new People(); 可以通過。
依據篇首圖形,我們知道實例(new出來的對象)含有 __proto__ 與 成員變量,正好與 prototype 一致,只不過缺少了 constructor,這個是有隱患的。
hasOwnProperty
用於判斷成員變量的,是不是prototype中的函數。
因為成員變量繼承了過來,已經變成自己的成員,所以hasOwnProperty是可以判斷基類的成員的。
如果 !hasOwnProperty,就會延著prototype鏈路檢索,直到null.
People.prototype.isPrototypeOf(m)
console.log(m instanceof Man) // true
console.log(m instanceof aaa) // false
js原型鏈與js繼承解析的更多相关文章
- js原型继承四步曲及原型继承图
一:js原型继承四步曲 //js模拟类的创建以及继承 //动物(Animal),有头这个属性,eat方法 //名字这个属性 //猫有名字属性,继承Animal,抓老鼠方法 //第一步:创建父类 fun ...
- js原型解析
我们都知道javascript因为具有了继承以及变量等等一系列的特性之后才被人们认为具有一门编程语言的资格,在后续的不断发展中,js在原生的基础上扩展了基于jquery等等的库,甚至衍生了像node. ...
- js原型及原型链解析
js原型.原型链 这几天闲了看了下js的原型,以下内容为个人理解,如有错误,尽请指正. 首先,明确一点:js中的对象分为普通对象和函数对象,一般我们自定义的可以被new的函数称作函数对象,另外js内置 ...
- JS 原型链图形详解
JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语 ...
- 对js原型简单的理解和图解
对js原型简单的理解和图解 最近在努力的学习js中,今天就抽了个空把自己理解的原型,记下一下在笔记中,以后自己查看,有空在会把原型链记录一下. 1.prototype prototype:是一个函数的 ...
- 【学习笔记】深入理解js原型和闭包(2)——函数和对象的关系
上文(深入理解jS原型和闭包(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; console.log ...
- 谈谈我认识的js原型
众所周知,JavaScript中是没有传统类的概念的,js通过原型链的方式实现继承.原型是js学习中的一大重点知识,在ES6出来之前,因为js不像php.java一样拥有类的写法,所以继承方式也就不像 ...
- JS原型链
JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...
- 深入分析JS原型链以及为什么不能在原型链上使用对象
在刚刚接触JS原型链的时候都会接触到一个熟悉的名词:prototype:如果你曾经深入过prototype,你会接触到另一个名词:__proto__(注意:两边各有两条下划线,不是一条).以下将会围绕 ...
随机推荐
- Java基础-SSM之Spring的AOP编程
Java基础-SSM之Spring的AOP编程 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. Spring的本质说白了就是动态代理,接下来我们会体验AOP的用法.它是对OOP的 ...
- 何凯文每日一句打卡||DAY7
- ant+sonar+jacoco代码质量代码覆盖率扫描
使用ant构建的java web项目如何做sonar代码质量扫描?以下就是实际遇到并成功使用的案例一.做sonar扫描的准备工作 1.给web项目增加build.xml构建脚本. 2.下载 ...
- C++ 修饰符类型
C++ 修饰符类型 C++ 允许在 char.int 和 double 数据类型前放置修饰符.修饰符用于改变基本类型的含义,所以它更能满足各种情境的需求. 下面列出了数据类型修饰符: signed u ...
- camera驱动框架分析(上)
前言 camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连接到soc的camif口上的,有些是通过usb接口导出的,如usb camera.我这里主要讨论前者, ...
- nginx参数优化
大家好,分享即关爱,我们很乐意和你分享一些新的知识,我们准备了一个 Nginx 的教程,分为三个系列,如果你对 Nginx 有所耳闻,或者想增进 Nginx 方面的经验和理解,那么恭喜你来对地方了. ...
- Linux本地解析文件/etc/hosts说明【原创】
windows的域名本地解析文件hosts是可以一个域名对多个IP,如果有一个IP有问题,可以去解析到其他IP Linux的本地解析文件/etc/hosts,是否也可以这样呢.下面做了个测试 先看一下 ...
- 新手学习爬虫之创建第一个完整的scrapy工程-糗事百科
创建第一个scrapy工程-糗事百科 最近不少小伙伴儿,问我关于scrapy如何设置headers的问题,时间久了不怎么用,还真有的忘,全靠记忆去写了,为了方便大家参考,也方便我以后的查阅,这篇文章就 ...
- 一个无锁消息队列引发的血案(四)——月:RingQueue(上) 自旋锁
目录 (一)起因 (二)混合自旋锁 (三)q3.h 与 RingBuffer (四)RingQueue(上) 自旋锁 (五)RingQueue(中) 休眠的艺术 (六)RingQueue(中) 休眠的 ...
- AngularJS里面$emit, $broadcast,$on,$http.Jsonp,constant是使用笔记
本片主要介绍$emit, $broadcast,$on经常开发的用法!