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

简介:

原型

一、什么是原型

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

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日

作者:技术金三胖

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

目录
相关文章
|
28天前
|
JavaScript 前端开发
如何在JavaScript中实现基于原型的继承机制
【8月更文挑战第14天】如何在JavaScript中实现基于原型的继承机制
24 0
|
8天前
|
JavaScript 前端开发
JavaScript基础知识-原型(prototype)
关于JavaScript基础知识中原型(prototype)概念的介绍。
18 1
|
27天前
|
JavaScript 前端开发
JavaScript中什么是原型?有什么用?
JavaScript中什么是原型?有什么用?
12 1
|
11天前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
28 0
|
1月前
|
JavaScript 前端开发 Java
什么是JavaScript原型对象
【8月更文挑战第2天】什么是JavaScript原型对象
47 9
|
19天前
|
JavaScript 前端开发 开发者
揭开JavaScript的神秘面纱:原型链背后隐藏的继承秘密
【8月更文挑战第23天】原型链是JavaScript面向对象编程的核心特性,它使对象能继承另一个对象的属性和方法。每个对象内部都有一个[[Prototype]]属性指向其原型对象,形成链式结构。访问对象属性时,若当前对象不存在该属性,则沿原型链向上查找。
23 0
|
3月前
|
设计模式 JavaScript 前端开发
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
JavaScript的继承机制基于原型链,它定义了对象属性和方法的查找规则。每个对象都有一个原型,通过原型链,对象能访问到构造函数原型上的方法。例如`Animal.prototype`上的`speak`方法可被`Animal`实例访问。原型链的尽头是`Object.prototype`,其`[[Prototype]]`为`null`。继承方式包括原型链继承(通过`Object.create`)、构造函数继承(使用`call`或`apply`)和组合继承(结合两者)。ES6的`class`语法是语法糖,但底层仍基于原型。继承选择应根据需求,理解原型链原理对JavaScript面向对象编程至关重要
70 7
【JavaScript】深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略
|
1月前
|
设计模式 JavaScript 前端开发
js对原型和继承的理解
了解JavaScript中原型和继承的概念对于编写优雅高效的代码、理解库和框架的内部机制以及执行高级设计模式都有着重要的意义。
35 0
|
1月前
|
JavaScript 前端开发
详细讲解!JavaScript原型 !
详细讲解!JavaScript原型 !
|
3月前
|
JavaScript
js奥义:原型与原型链(1)
js奥义:原型与原型链(1)