javascript代码实例教程-javascript 原型、原型链、对象复制等原理和示例分析(下)

发布时间:2019-01-18 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了javascript代码实例教程-javascript 原型、原型链、对象复制等原理和示例分析(下)脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

原型
原型是 JavaScript 面向对象特性中重要的概念,也是大家太熟悉的概念。因为在绝大多
数的面向对象语言中,对象是基于类的(例如 Java 和 C++ ) ,对象是类实例化的结果。而在
JavaScript 语言中,没有类的概念
① ,对象由对象实例化。打个比方来说,基于类的语言中类
就像一个模具,对象由这个模具浇注产生,而基于原型的语言中,原型就好像是一件艺
的原件,我们通过一台 100% 精确的机器把这个原件复制出很多份。
前面小节的例子中都没有涉及原型,仅仅通过构造函数和 new 语句生成类,让我们看
看如何使用原型和构造函数共同生成对象。
function PErson() {}
Person.PRototype.name = ‘BYVoid’;
Person.prototype.showName = function() {
console.LOG(this.name);
};
VAR person = new Person();
person.showName();
上面这段代码使用了原型而不是构造函数初始化对象。 这样做与直接在构造函数内定义
属性有什么不同呢?
**构造函数内定义的属性继承方式与原型不同, 子对象需要显式调用父对象才能继承构
造函数内定义的属性。
构造函数内定义的任何属性, 包括函数在内都会被重复创建, 同一个构造函数产生的
两个对象不共享实例。**
构造函数内定义的函数有运行时闭包的开销, 因为构造函数内的局部变量对其中定义
的函数来说也是可见的。
下面这段代码可以验证以上问题:
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 生成原型对象。
图解析了它们之间错综复杂的关系。

javascript代码实例教程-javascript 原型、原型链、对象复制等原理和示例分析(下)

对象的复制
JavaScript 和 Java 一样都没有像c语言中一样的指针,所有对象类型的变量都是指向对
象的引用,两个变量之间赋值传递一个对象并不会对这个对象进行复制,而只是传递引用。
有些时候我们需要完整地复制一个对象,这该如何做呢? Java 语言中有 clone 方法可以实
现对象复制,但 JavaScript 中没有这样的函数。因此我们需要手动实现这样一个函数,一个
简单的做法是复制对象的所有属性:<"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPk9iamVjdC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvBigpIHs8YnIgLz4NCnZhciBuZXdPYmogPSB7fTs8YnIgLz4NCmZvciAodmFyIGkgaW4gdGhpcykgezxiciAvPg0KbmV3T2jqW2ldID0gdGhpc1tpXTs8YnIgLz4NCn08YnIgLz4NCnJldHVybiBuZXdPYmo7PGJyIC8+DQp9PGJyIC8+DQp2YXIgb2JqID0gezxiciAvPg0KbmFtZTogJmxzcXVvO2J5dm9pZCZyc3F1bzssPGJyIC8+DQpsaWtlczogWyZsc3F1bztub2RlJnJzcXVvO108YnIgLz4NCn07PGJyIC8+DQp2YXIgbmV3T2JqID0gb2JqLmNsb25lKCk7PGJyIC8+DQpvYmoubGlrZXMucHVzaCgmbHNxdW87cHl0aG9uJnJzcXVvOyk7PGJyIC8+DQpjb25zb2xlLmxvZyhvYmoubGlrZXMpOyAvLyDK5LP2IFsgJmxzcXVvO25vZGUmcnNxdW87LCAmbHNxdW87cHl0aG9uJnJzcXVvOyBdPGJyIC8+DQpjb25zb2xlLmxvZyhuZXdPYmoubGlrZXMpOyAvLyDK5LP2IFsgJmxzcXVvO25vZGUmcnNxdW87LCAmbHNxdW87cHl0aG9uJnJzcXVvOyBdPC9wPg0KPHA+yc/D5rXEtPrC68rH0ru49rbUz/PHs7+9sbSjqHNoYWxsb3cgY29weaOptcTKtc/Wo6y8tNa7uLTWxrv5sb7A4NDNtcTK9NDUo6y2+DxiciAvPg0KubLP7bbUz/PA4NDNtcTK9NDUoaMgx7O/vbG0tcTOysziysc8c3Ryb25nPsG9uPa21M/zubLP7bbUz/PA4NDNtcTK9NDUPC9zdHJvbmc+o6wgwP3I58nPwP3W0CBsaWtlcyDK9DxiciAvPg0K0NTWuM/ytcTKx82s0ru49sr91+mhozxiciAvPg0Kyrxp1tK7uPbN6sirtcS4tNbGo6y78snuv72xtKOoZGVLCCBjb3B5o6myorK7ysfSu7z+yN3S17XEysKjrNLyzQQz/cHLu/mxvsr9vt08YnIgLz4NCsDg0M2jrLu509C24NbWsrvNrLXEttTP86OsttTP88Tasr+7udPQuLTU07XEveG5uaOs0vK0y9Do0qrTw7Xduem1xLe9yr3AtMq1z9ajujwvcD4NCjxwPk9iamVjdC5wcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbigpIHs8YnIgLz4NCnZhciBuZXdPYmogPSB7fTs8YnIgLz4NCmZvciAodmFyIGkgaW4gdGhpcykgezxiciAvPg0KaWYgKhr5cGVvZih0aGlzW2ldKSA9PSAmbHNxdW87b2JqZWN0JnJzcXVvOyA="| typeof(this[i]) == ‘function’) {
newObj[i] = this[i].clone();
} else {
newObj[i] = this[i];
}
}
return newObj;
};
Array.prototype.clone = function() {
var newArray = [];
for (var i = 0; i < this.length; i++) {
if (typeof(this[i]) == ‘object’ || typeof(this[i]) == ‘function’) {
newArray[i] = this[i].clone();
} else {
newArray[i] = this[i];
}
}
return newArray;

};
Function.prototype.clone = function() {
var that = this;
var newFunc = function() {
return that.apply(this, arguments);
};
for (var i in this) {
newFunc[i] = this[i];
}
return newFunc;
};
var obj = {
name: ‘byvoid’,
likes: [‘node’],
display: function() {
console.log(this.name);
},
};
var newObj = obj.clone();
newObj.likes.push(‘python’);
console.log(obj.likes); // 输出 [ ‘node’ ]
console.log(newObj.likes); // 输出 [ ‘node’, ‘python’ ]
console.log(newObj.display == obj.display); // 输出 false

上面这个实现看起来很完美,它不仅递归地复制了对象复杂的结构,还实现了函数的深
拷贝。这个方法在大多数情况下都很好用,但有一种情况它却无能为力,例如下面的代码:
var obj1 = {
ref: null
};
var obj2 = {
ref: obj1
};
obj1.ref = obj2;
这段代码的逻辑非常简单,就是两个相互引用的对象。当我们试图使用深拷贝来复制
obj1 和 obj2 中的任何一个时,问题就出现了。因为深拷贝的做法是遇到对象就进行递归
复制,那么结果只能无限循环下去。对于这种情况,简单的递归已经无法解决,必须设计一
套**图论算法, 分析对象之间的依赖关系, 建立一个拓扑结构图, 然后分别依次复制每个顶点,
并重新构建它们之间的依赖关系**。

觉得可用,就经常来吧! 脚本宝典 欢迎评论哦!&nbsp;js脚本,巧夺天工,精雕玉琢。小宝典献丑了!

脚本宝典总结

以上是脚本宝典为你收集整理的javascript代码实例教程-javascript 原型、原型链、对象复制等原理和示例分析(下)全部内容,希望文章能够帮你解决javascript代码实例教程-javascript 原型、原型链、对象复制等原理和示例分析(下)所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。