javascript成神之路(2):深入理解原型以及原型链的重要性

简介:

原型

一、什么是原型

每个函数对象都有一个prototype属性,这个属性这个属性是一个指针,指向一个对象。当函数作为构造函数使用时这个对象会成为调用该构造函数而创建的实例的原型,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。是不是感觉一脸懵逼呢?我们先看看下面一个例子: 

function Sanpang(val) { this.valueA = val; } Sanpang.prototype.sayHello = function () { console.log(this.valueA); } var f1 = new Sanpang(1); var f2 = new SanpangF(2); // 由F函数生成的实例都会包含sayA方法 f1.sayHello(); f2.sayHello();

就是说,构造函数生成的实例会有一组共享的属性和方法,这些属性和方法在构造函数的原型对象里。看到这里大家应该稍微有点眉目了吧。

二、原型的使用方式

1.在赋值原型prototype的时候使用function立即执行的表达式来赋值,示例如下:

A.prototype = function () { } ();

这种方法的好处就是可以封装私有的function,通过return的形式暴露出简单的使用名称,以达到public/private的效果。

A.prototype = function () { addF = function (x, y) { return x + y; }, subtractF = function (x, y) { return x - y; } return { add: addF, subtract: subtractF } } ();

调用的时候我们用new A.add(1,2),这样我们就计算出结果了。

2.分开设置每个原型的属性,示例如下:

var B = function () { this.decimalDigits = 11; }; B.prototype.add = function (x, y) { return x + y; }; B.prototype.subtract = function (x, y) { return x - y; };

第一种方式就是一次性设置了原型对象,所以有一定的弊端。这样我们就声明了一个B对象,构造函数里会初始化一个小数位数的属性decimalDigits,然后通过原型属性设置2个function,分别是add(x,y)和subtract(x,y),当然你也可以使用前面提到的2种方式的任何一种,我们的主要目的是看如何将B对象设置到真正的C的原型上。

var B = function() { this.decimalDigits = 2; }; B.prototype = { add: function(x, y) { return x + y; }, subtract: function(x, y) { return x - y; } };

当上B创建成功以后我们开始设置C

var C = function () { this.tax = 5; //每一个实例都有这个tax属性 }; C.prototype = new B();

这样的话C的原型是指向到B的一个实例上,目的是让C集成它的add(x,y)和subtract(x,y)这2个function,由于它的原型是B的一个实例,所以不管你创建多少个C对象实例,他们的原型指向的都是同一个实例。这样我们就可以运行下面的代码:

var c = new C(); alert(c.add(1, 1)); //B 里声明的decimalDigits属性,在 C里是可以访问到的 alert(c.decimalDigits); //同样是可以访问到的

如果我不想让C访问B的构造函数里声明的属性值,那该杂么做?

var C = function () { this.tax= 5; }; C.prototype = B.prototype;

这样通过将B的原型赋给C的原型,这样你在C的实例上就访问不到那个decimalDigits值了,如果你访问下面的代码将会报错。

var c = new C(); alert(c.add(1, 1)); alert(c.decimalDigits);

3.重写原型:

当我们使用第三方javascript类库的时候,往往有时候他们定义的原型方法是不能满足我们的需要,但是又离不开这个类库,所以这时候我们就需要重写他们的原型中的一个或者多个属性或function,我们可以通过继续声明的同样的add代码的形式来达到覆盖重写前面的add功能,代码如下:

覆盖前面C的add() function C.prototype.add = function (x, y) { return x + y + this.tax; }; var c = new C(); alert(c.add(2, 2));

我们现在调用的结果就比原来多出了一个tax的值,但是有一点需要注意:那就是重写的代码需要放在最后,这样才能覆盖前面的代码。

原型链

原型链,是JS实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。示例如下:

function F() { this.value = 1; } F.prototype = { method: function() {} }; function B() {} B.prototype = new F(); B.prototype.foo = 'Hello World'; // 修正B.prototype.constructor为B本身 B.prototype.constructor = B; var test = new B() // 创建B的一个新实例 // 原型链 t => [B的实例] B.prototype [F的实例] { foo: 'Hello World' } F.prototype {method: ...}; Object.prototype {toString:等等};

以上的例子,t 对象从 B.prototype 和 F.prototype 继承下来;因此,它能访问 F 的原型方法 method。同时,它也能够访问那个定义在原型上的 F 实例属性 value。需要注意的是 new B() 不会创造出一个新的 F 实例,而是重复使用它原型上的那个实例;因此,所有的 B 实例都会共享相同的 value 属性。

总结

  • 原型和原型链是 JS 实现继承的一种模型。
  • 原型链是靠 _proto _ 形成的,而不是 prototype。
  • 所有的原型对象都有 constructor 属性,该属性对应创建所有指向该原型的实例构造函数。
  • 函数对象和原型对象通过 prototype 和 constructor 属性进行相互关联。

原文发布时间:2018年01月07日

作者:技术金三胖

本文来源:开源中国  如需转载请联系原作者

目录
相关文章
|
10月前
|
存储 JavaScript 前端开发
原型链:揭开JavaScript背后的神秘面纱
原型链:揭开JavaScript背后的神秘面纱
|
9月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
175 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
|
JSON JavaScript 前端开发
|
存储 JavaScript 前端开发
JavaScript对象与原型:揭示编程世界的奥秘
JavaScript对象与原型:揭示编程世界的奥秘
46 0
|
JavaScript 前端开发
深度剖析之由浅入深揭秘JavaScript类型转换(最全总结篇)(二)
深度剖析之由浅入深揭秘JavaScript类型转换(最全总结篇)(二)
|
存储 前端开发 JavaScript
前端祖传三件套JavaScript的对象之基础概念的方法
在 JavaScript 中,对象是一个非常重要的数据类型,用于表示一组相关属性和方法。每个对象都有一些方法,这些方法可以是对象自身定义的方法,也可以是从原型链中继承而来的方法。本文将介绍对象方法的概念、分类和使用方法。
99 0
|
存储 前端开发 JavaScript
前端祖传三件套JavaScript的对象之基础概念的属性
在 JavaScript 中,对象是一种非常重要的数据类型,用于表示一组相关属性和方法。每个对象都有一些属性,这些属性可以是数据属性或访问器属性。本文将介绍对象属性的概念、分类和使用方法。
122 0
|
前端开发
前端知识案例66-javascript基础语法-原型
前端知识案例66-javascript基础语法-原型
53 0
前端知识案例66-javascript基础语法-原型
|
前端开发 JavaScript
前端知识案例-javascript深拷贝
前端知识案例-javascript深拷贝
190 0
前端知识案例-javascript深拷贝
|
前端开发 JavaScript 数据安全/隐私保护
Web前端开发笔记——第四章 JavaScript程序设计 第六节 函数
Web前端开发笔记——第四章 JavaScript程序设计 第六节 函数
Web前端开发笔记——第四章 JavaScript程序设计 第六节 函数