javascript中一切皆对象,但是由于没有Class类的概念,所以就无法很好的表达对象与对象之间的关系了。

比如对象A与对象B之间,它们两个是相对独立的个体,互不干扰,对象A修改自身的属性不会影响到对象B。

虽然这很好,但是有一个问题,如果对象A与对象B都有一个方法 run() ,并且代码也一样,那对象A与对象B各自都独立拥有一份 run() 方法的完整代码,这是需要资源去保存的。

一旦我们程序中应用的对象过多,那这种资源消耗会是巨大的。那有没有一种方法可以让对象A与对象B拥有一些公共的属性和方法,让它们之前有某种联系?

我们设想一下,会不会存在一个 common对象(公共对象),common对象上保存着公共的属性和方法,而对象A与对象B里面有一个prototype属性指向这个 common对象,

当然我们调用对象A或对象B的属性和方法时,如果在自身对象中没有找到,就去prototype这个属性指向的对象上面去找。

而common对象本身也有一个prototype属性指向更上一级的common对象,然后一直往上找啊找,直到为null,就停止。

这种不断的从下往上找的这种路径,就像链条一样,我们称它为 原型链,而那个common对象,我们称它为 原型对象。

我们来看一个构造函数

function Base(name) {
this.name = name;
} let A = new Base('A');
let B = new Base('B'); //每一个函数都有一个prototype属性,指向该函数的原型对象
console.log(Base.prototype); //当然原型对象也是一个对象,它也有一个constructor,指向构造函数
console.log(Base.prototype.constructor === Base); //每一个实例对象的constructor都指向创建它们的构造函数
console.log(A.constructor === Base);
console.log(B.constructor === Base); //每一个实例对象都有一个__proto__属性,该属性指向构造函数的原型对象
console.log(A.__proto__ === Base.prototype);
console.log(B.__proto__ === Base.prototype);

1、每一个函数都有一个prototype属性,它指向该函数的原型对象。

2、原型对象也是对象,它也有自已的constructor,它指向构造函数Base()。换句话说,其实原型对象也是构造函数Base()的一个实例。只不过比较特殊,用来存放公共属性和方法的。

3、每一个通过构造函数Base()创建的实例对象,都有一个constructor,指向创建它们的构造函数。

4、每一个对象,都有一个 __proto__ 属性,指向构造函数Base()的 原型对象。换句话说,__proto__ 是将 原型 串联起来形成链条的关键。不然对象A与对象B都无法找到原型对象上的公共属性和方法。

function Base(name) {
this.name = name;
}
//我们在原型对象上添加公共属性
Base.prototype.status = '开始';
//我们在原型对象上添加公共方法
Base.prototype.run = function() {
console.log(this.name + ' run ...');
}; let A = new Base('A');
let B = new Base('B'); A.run();
B.run(); console.log(A.status);
console.log(B.status); //修改原型上的属性,则实例对象也会跟着改变
Base.prototype.status = '停止'; console.log(A.status);
console.log(B.status);

通过原型与原型链,让对象与对象之间有了关联关系。

那如何通过原型与原型链,让一个构造函数继承于另一个构造函数?

比如,我们要让构造函数Child 继承于 构造函数Base,只需要让 Child 的 prototype 指向 Base的 原型对象,不就可以了?

function Base(name) {

}

Base.prototype.name = 'Base';
Base.prototype.run = function () {
console.log(this.name + ' run ...');
}; function Child() { } Child.prototype = Base.prototype;
//注意这个时候,Child.prototype对象的constructor属性指向了Base
//这就导致通过构造函数Child创建的实例对象,对象的constructor属性会指向Base,而不是Child,这会导致混乱。
//所以我们重新设置Child.prototype.constructor指向Child
Child.prototype.constructor = Child; let c = new Child(); console.log(c.name);
c.run();

这样有一个问题,Child.prototype 与 Base.prototype 指向同一个原型对象,任何对 Child.prototype 的修改都会反应到 Base.prototype 上面。

这时,Base.prototype.constructor 指向了 Child,这显然是有问题。

我们只能通过一个中间的空构造函数,来完成原型的指向。

function Base(name) {

}

Base.prototype.name = 'Base';
Base.prototype.run = function () {
console.log(this.name + ' run ...');
}; function Child() { } //创建一个中间的空构造函数
function Mid() { } //让该空构造函数的prototype指向Base的原型对象
Mid.prototype = Base.prototype;
//再让Child的prototype指向该空构造函数的一个实例
Child.prototype = new Mid();
//这样,当修改Child.prototype.constructor时,Base.prototype就不会受影响了
Child.prototype.constructor = Child; let c = new Child(); console.log(c.name);
c.run(); //Base.prototype的constructor仍然指向Base,没有受到影响
console.log(Base.prototype.constructor);

  

那怎么通过原型与原型链,让你一对象继承于另一个对象呢?

比如,我们要让对象B继承于对象A,无非就是想要拿到对象A的属性和方法,这么一想,那通过把对象B的 __proto__  指向 对象A,不就可以实现了?

let A = {
name: 'A',
run() {
console.log(this.name + ' run ...');
}
};
console.log(A.name);
A.run(); let B = {};
//让对象B的__proto__指向对象A
B.__proto__ = A;
//当对象B调用run()方法时会在自身上找,如果没找到,则通过__proto__向上找
//由于__proto__指向对象A,所以最终会在对象A中找到run()方法
B.run(); B.__proto__.name = 'B';
console.log(A.name);
console.log(B.name);

这样有一个问题,当修改 B.__proto__.name = 'B'; 时,对象A也会受到影响。

我们可以通过ES5提供的 Object.create() 来解决此问题,Object.create()可以通过指定的 原型对象 创建一个新对象。

let A = {
name: 'A',
run() {
console.log(this.name + ' run ...');
}
};
console.log(A.name);
A.run(); let B = {};
//通过Object.create()创建一个以对象A为原型对象的新对象
//让对象B的__proto__指向该新对象
//这样再操作B.__proto__中的属性就与对象A无关了。
B.__proto__ = Object.create(A); B.run(); B.__proto__.name = 'B';
console.log(A.name);
console.log(B.name);

javascript 的原型与原型链的理解的更多相关文章

  1. javascript执行环境以及作用域链的理解

    在javascript脚步语言中执行环境有两种: 全局环境: 局部环境: 我们可以拿一个田径跑道来打比方,全局环境就可以理解为是最外面跑道,它包含着内部所有的东西,有人在跑步,有人在跳远,这些用着不同 ...

  2. 【JavaScript】深入理解JavaScript之强大的原型和原型链

    由于JavaScript是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的,今天我们就来了解一下原型和原型链. AD: hasOwnProperty函数: hasOw ...

  3. <深入理解JavaScript>学习笔记(5)_强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. (prototypal :原型.学好英语还是很重要的) 虽然这经常被当作是 JavaScript 的缺点 ...

  4. 深入理解JavaScript系列(5):强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大.实 ...

  5. javascript系列--认识并理解构造函数,原型和原型链

    一.前言 介绍构造函数,原型,原型链.比如说经常会被问道:symbol是不是构造函数:constructor属性是否只读:prototype.[[Prototype]]和__proto__的区别:什么 ...

  6. 如何理解JavaScript的原型和原型链

    在现在的业务开发中,应该很少人在写原生JavaScript了,大家都一股脑地扑在各个框架上.本来,这些框架对于业务和开发者来说是一种福音,减少了各种各样的开发痛点,但是带来的负面问题就是对于开发者来说 ...

  7. javascript原型与原型链个人理解

    想了解原型和原型链,我觉得首先我们得知道javascript里有一个Object 与 Function,它俩都是构造函数,当然函数也是一个对象.我们打印Object 与 Function看一下, co ...

  8. 上帝视角一文理解JavaScript原型和原型链

    本文呆鹅原创,原文地址:https://juejin.im/user/307518987058686/posts 前言 本文将从上帝角度讲解JS的世界,在这个过程中,大家就能完全理解JS的原型和原型链 ...

  9. javascript 原型及原型链的初步理解

    最近折腾了好久,终于是把js里面的原型和原型链做了个初步的理解: 在这里,我打个比喻: 我(child),我妈constructor(构造函数)生了我:别人问我老妈跟谁生的我,于是此时我妈会指向我爸爸 ...

  10. [我的理解]Javascript的原型与原型链

    一.原型与原型链的定义 原型:为其他对象提供共享属性的对象 注:当构造器创建一个对象,为了解决对象的属性引用,该对象会隐式引用构造器的"prototype"属性.程序通过const ...

随机推荐

  1. UNITY 的GC ALLOC到底是什么

    U3D的Profiler中的GC ALLOC 项让人很麻烦,一直搞不清楚它是什么,因为 GC 是垃圾回收,而alloc是内存分配,那么 GC ALLOC 是 垃圾回收内存分配? 这个名字起的太TM烂了 ...

  2. servlet编码问题

    建议每个servlet都写上    request.setCharacterEncoding("UTF-8")

  3. nth-child与nth-of-type区别

    示例详细理解:nth-child(n)与:nth-of-type(n)区别 childselector:nth-child(index) 1,子选择器(childselector,这里是p选择器)选中 ...

  4. Myeclipse2017 安装反编译插件和SVN插件

    亲测有效 2018年1月22日10:36:33 https://www.cnblogs.com/liuyk-code/p/7519886.html

  5. django 认证系统--3

    WEB request中的认证 django使用sessions和middleware和reqeust对象联系在一起 它们通过给每一个reqeust请求添加一个request.user属性来代表当前用 ...

  6. asp.net控件中的reportview不显示

    如果reportview在asp.net中,图标出不来,打X 1.安装reportview控件(在装有vs2010中的电脑中搜,不要去下载,下载可能会出错) 2.如果是iis7以上版本,web.con ...

  7. VIM+ctags+cscope

    VIM+ctags+cscope用法: http://blog.csdn.net/hnllei/article/details/7407124 http://blog.csdn.net/luckywa ...

  8. 2018面向对象程序设计(Java)第3周学习指导及要求

    2018面向对象程序设计(Java) 第3周学习指导及要求(2018.9.11-2018.9.16)   学习目标 适应老师教学方式,能按照自主学习要求完成本周理论知识学习: 掌握Java Appli ...

  9. Java计算计算活了多少天

    Java计算计算活了多少天 思路: 1.输入你的出现日期: 2.利用日期转换,将字符串转换成date类型 3.然后将date时间换成毫秒时间 4.然后获取当前毫秒时间: 5.最后计算出来到这个时间多少 ...

  10. html开发环境

    标签(空格分隔): 环境 开发环境: 市面上有很多的HTML编辑器可以选择,常见的Hbuild.Sublime Text.Dreamweare都可以用来开发HTML. 当然PyCharm也支持HTML ...