(一)需要
最近在看八股文,看到了原型链看到的知识点。开发时,可能用的1-2种多一些。没想到有这么多。MDN上,我发现有的点和控制台打印的有不统一的中央。就想着本人记录下来,之后有问题也便于查找和修整。
(二)四种形式
1、应用语法结构创立的对象
var o = {a: 1};// o 这个对象继承了 Object.prototype 下面的所有属性// o 本身没有名为 hasOwnProperty 的属性// hasOwnProperty 是 Object.prototype 的属性// 因而 o 继承了 Object.prototype 的 hasOwnProperty// Object.prototype 的原型为 null// 原型链如下:// o ---> Object.prototype ---> nullvar a = ["yo", "whadup", "?"];// 数组都继承于 Array.prototype// (Array.prototype 中蕴含 indexOf, forEach 等办法)// 原型链如下:// a ---> Array.prototype ---> Object.prototype ---> nullfunction f(){ return 2;}// 函数都继承于 Function.prototype// (Function.prototype 中蕴含 call, bind等办法)// 原型链如下:// f ---> Function.prototype ---> Object.prototype ---> null
2、应用结构器创立的对象
在 JavaScript 中,结构器其实就是一个一般的函数。当应用 new 操作符 来作用这个函数时,它就能够被称为构造方法(构造函数)。
function Graph() { this.vertices = []; this.edges = [];}Graph.prototype = { addVertex: function(v){ this.vertices.push(v); }};var g = new Graph();console.log(g)// g 是生成的对象,他的本身属性有 'vertices' 和 'edges'。// 在 g 被实例化时,g.[[Prototype]] 指向了 Graph.prototype。
3、应用 Object.create
创立的对象
ECMAScript 5 中引入了一个新办法:Object.create()
。能够调用这个办法来创立一个新对象。新对象的原型就是调用 create 办法时传入的第一个参数:
var a = {a: 1};// a ---> Object.prototype ---> nullvar b = Object.create(a);// b ---> a ---> Object.prototype ---> nullconsole.log(b.a); // 1 (继承而来)var c = Object.create(b);// c ---> b ---> a ---> Object.prototype ---> nullvar d = Object.create(null);// d ---> nullconsole.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype
4、应用 class
关键字创立的对象
ECMAScript6 引入了一套新的关键字用来实现 class。应用基于类语言的开发人员会对这些构造感到相熟,但它们是不同的。JavaScript 依然基于原型。这些新的关键字包含 class
, constructor
,static
,extends
和 super
。
"use strict";class Polygon { constructor(height, width) { this.height = height; this.width = width; }}class Square extends Polygon { constructor(sideLength) { super(sideLength, sideLength); } get area() { return this.height * this.width; } set sideLength(newLength) { this.height = newLength; this.width = newLength; }}var square = new Square(2);
(三)四种创建对象的劣势和毛病比照
名称 | 例子 | 劣势 | 缺点 |
---|---|---|---|
New-initialization | function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto = new foo; proto.bar_prop = "bar val"; bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop); Copy to Clipboard | 反对目前以及所有可设想到的浏览器(IE5.5都能够应用)。 这种办法十分快,十分符合标准,并且充分利用JIT优化。 | 为应用此办法,必须对相干函数初始化。 在初始化过程中,构造函数能够存储每个对象必须生成的惟一信息。然而,这种惟一信息只生成一次,可能会带来潜在的问题。此外,构造函数的初始化,可能会将不须要的办法放在对象上。然而,如果你只在本人的代码中应用,你也分明(或有通过正文等写明)各段代码在做什么,这些在大体上都不是问题(事实上,通常是有好处的)。 |
Object.create | function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto = Object.create( foo.prototype ); proto.bar_prop = "bar val"; bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop); Copy to Clipboard function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto = Object.create( foo.prototype, { bar_prop: { value: "bar val" } } ); bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop) Copy to Clipboard | 反对以后所有非微软版本或者 IE9 以上版本的浏览器。容许一次性地间接设置 __proto__ 属性,以便浏览器能更好地优化对象。同时容许通过 Object.create(null) 来创立一个没有原型的对象。 | 不反对 IE8 以下的版本。然而,随着微软不再对系统中运行的旧版本浏览器提供反对,这将不是在大多数利用中的次要问题。 另外,这个慢对象初始化在应用第二个参数的时候有可能成为一个性能黑洞,因为每个对象的描述符属性都有本人的形容对象。当以对象的格局解决成千盈百的对象形容的时候,可能会造成重大的性能问题。 |
Object.setPrototypeOf | function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto = { bar_prop: "bar val" }; Object.setPrototypeOf( proto, foo.prototype ); bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop); Copy to Clipboard function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto; proto=Object.setPrototypeOf( { bar_prop: "bar val" }, foo.prototype ); bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop) Copy to Clipboard | 反对所有古代浏览器和微软IE9+浏览器。容许动静操作对象的原型,甚至能强制给通过 Object.create(null) 创立进去的没有原型的对象增加一个原型。 | 这个形式体现并不好,应该被弃用。如果你在生产环境中应用这个办法,那么疾速运行 Javascript 就是不可能的,因为许多浏览器优化了原型,尝试在调用实例之前猜想办法在内存中的地位,然而动静设置原型烦扰了所有的优化,甚至可能使浏览器为了运行胜利,应用齐全未经优化的代码进行重编译。 不反对 IE8 及以下的浏览器版本。 |
proto | function foo(){} foo.prototype = { foo_prop: "foo val" }; function bar(){} var proto = { bar_prop: "bar val", __proto__: foo.prototype }; bar.prototype = proto; var inst = new bar; console.log(inst.foo_prop); console.log(inst.bar_prop); Copy to Clipboard var inst = { __proto__: { bar_prop: "bar val", __proto__: { foo_prop: "foo val", __proto__: Object.prototype } } }; console.log(inst.foo_prop); console.log(inst.bar_prop) Copy to Clipboard | 反对所有古代非微软版本以及 IE11 以上版本的浏览器。将 __proto__ 设置为非对象的值会静默失败,并不会抛出谬误。 | 应该齐全将其摈弃因为这个行为齐全不具备性能可言。 如果你在生产环境中应用这个办法,那么疾速运行 Javascript 就是不可能的,因为许多浏览器优化了原型,尝试在调用实例之前猜想办法在内存中的地位,然而动静设置原型烦扰了所有的优化,甚至可能使浏览器为了运行胜利,应用齐全未经优化的代码进行重编译。不反对 IE10 及以下的浏览器版本。 |
以上
参考链接
https://developer.mozilla.org...