JS原型详解

IT教程 4年前 (2020) https://www.leileyou.com

原形

原型

原型是 JavaScript 面向对象特性中重要的概念,也是大家太熟悉的概念。因为在绝大多 

数的面向对象语言中,对象是基于类的(例如 Java 和 C++ ),对象是类实例化的结果。而在 

JavaScript 语言中,没有类的概念①,对象由对象实例化。打个比方来说,基于类的语言中类 

就像一个模具,对象由这个模具浇注产生,而基于原型的语言中,原型就好像是一件艺术品 

的原件,我们通过一台 100% 精确的机器把这个原件复制出很多份。 

 让我们看看如何使用原型和构造函数共同生成对象。

function Person() {
}
Person.prototype.name = 'BYVoid';
Person.prototype.showName = function () {
console.log(this.name);
};
var person = new Person();
person.showName();

上面这段代码使用了原型而不是构造函数初始化对象。这样做与直接在构造函数内定义 

属性有什么不同呢? 

1. 构造函数内定义的属性继承方式与原型不同,子对象需要显式调用父对象才能继承构 造函数内定义的属性。 

2. 构造函数内定义的任何属性,包括函数在内都会被重复创建,同一个构造函数产生的 两个对象不共享实例。 

3. 构造函数内定义的函数有运行时闭包的开销,因为构造函数内的局部变量对其中定义 的函数来说也是可见的。

下面这段代码可以验证以上问题:

function Foo() {
var innerVar = 'hello';
this.prop1 = 'BYVoid';
this.func1 = function(){
innerVar = '';
};
}
Foo.prototype.prop2 = 'Carbo';
Foo.prototype.func2 = function () {
console.log(this.prop2);
};
var foo1 = new Foo();
var foo2 = new Foo();
console.log(foo1.func1 == foo2.func1); // 输出 false
console.log(foo1.func2 == foo2.func2); // 输出 true

尽管如此,并不是说在构造函数内创建属性不好,而是两者各有适合的范围。那么我们 

什么时候使用原型,什么时候使用构造函数内定义来创建属性呢?

除非必须用构造函数闭包,否则尽量用原型定义成员函数,因为这样可以减少开销。

尽量在构造函数内定义一般成员,尤其是对象或数组,因为用原型定义的成员是多个 实例共享的。

接下来,我们介绍一下JavaScript中的原型链机制。

原型链

JavaScript 中有两个特殊的对象: Object 与 Function,它们都是构造函数,用于生 

成对象。 Object.prototype 是所有对象的祖先, Function.prototype 是所有函数的原 

型,包括构造函数。我把 JavaScript 中的对象分为三类,一类是用户创建的对象,一类是**构 

造函数对象,一类是原型对象**。用户创建的对象,即一般意义上用 new 语句显式构造的对 

象。构造函数对象指的是普通的构造函数,即通过 new 调用生成普通对象的函数。原型对象 

特指构造函数 prototype 属性指向的对象。这三类对象中每一类都有一个 proto 属 

性,它指向该对象的原型,从任何对象沿着它开始遍历都可以追溯到 Object.prototype。 

构造函数对象有 prototype 属性,指向一个原型对象,通过该构造函数创建对象时,被创 

建对象的 proto 属性将会指向构造函数的 prototype 属性。原型对象有 constructor 

属性,指向它对应的构造函数。让我们通过下面这个例子来理解原型:

function Foo() {
}
Object.prototype.name = 'My Object';
Foo.prototype.name = 'Bar';
var obj = new Object();
var foo = new Foo();
console.log(obj.name); // 输出 My Object
console.log(foo.name); // 输出 Bar
console.log(foo.__proto__.name); // 输出 Bar
console.log(foo.__proto__.__proto__.name); // 输出 My Object
console.log(foo. __proto__.constructor.prototype.name); // 输出 Bar

我们定义了一个叫做 Foo ()的构造函数,生成了对象 foo。同时我们还分别给 Object 

和 Foo 生成原型对象。 

图A-1 解析了它们之间错综复杂的关系 

                  图 A-1 JavaScript 原型之间的关系

在 JavaScript 中,继承是依靠一套叫做原型链(prototype chain)的机制实现的。属性 

继承的本质就是一个对象可以访问到它的原型链上任何一个原型对象的属性。例如上例的 

foo 对象,它拥有 foo. _ _ proto_ _ 和 foo. _ _ proto_ _ . _ _ proto _ _ 所有属性的浅拷 

贝(只复制基本数据类型,不复制对象)。所以可以直接访问foo.constructor(来自foo. 

_ _ proto_ _ ,即Foo.prototype), foo.toString(来自foo. _ _ proto_ _ . _ _ proto__, 

即Object.prototype)。 

Java socket详解

转:https://www.jianshu.com/p/cde27461c226 一:socket通信基本原理。  首先socket 通信是基于TCP/IP 网络层上的一种传送方式,我

Java中Class.forName()函数用法 原理 详解

1.在一些应用中,无法事先知道使用者将加载什么类,而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态

详解怎么把hao123设置为主页

最近小编发现有小伙伴想知道将hao123设置为主页的方法,然后小编就花了些时间来了解这个,所以,现在小编就来给大家伙说说如何将hao123

详解win8如何激活

win8是一款具有革命性变化的操作系统,取消了开始菜单,采用了动态磁贴模式。非常易于触屏用户的使用。下面,我就给大家介绍一下激活wi

《啪嗒砰3》职业系统详解

内容摘要:游戏有三种基础职业,分别为盾剑兵、枪兵和弓手,每种基础职业又分别对应6中衍生职业,随着等级的提升会开放相对应的衍生职业

文章回顾

大家看了本文JS原型详解的精彩教程资源内容,是不是对JS原型详解了解更多,真心希望JS原型详解能帮助到你, 小编会一直给你带来更多教程资源文章信息。

版权声明: 发表于 2020-01-01 8:17:33。

本文在撰写过程中会借鉴文案,对内容不作任何保证或承诺,请读者自行参考斟酌。网站发布的信息(包含但不限于版式、图片、字体、文章等素材)由第三方用户分享,版权归原作者所有,本站不承担任何相关的版权纠纷等相关责任。如您认为本篇内容侵犯了您的权益,请与我们联系,我们会及时处理。

本文标题:JS原型详解