原型和原型链

原型

JavaScript 这门语言没有类的概念,所以 JavaScript 并非是基于类的继承,而是基于原型的继

JavaScript 摒弃类转而使用原型作为实现继承的基础,是因为基于原型的继承相比基于类的继承上在概念上更为简单。首先我们明确一点,类存在的目的是为了实例化对象,而 JavaScript 可以直接通过对象字面量语法轻松的创建对象。

每一个函数,都有一个 prototype 属性。 所有通过函数 new 出来的对象,这个对象都有一个 __proto__ 指向这个函数的 prototype
当你想要使用一个对象(或者一个数组)的某个功能时:如果该对象本身具有这个功能,则直接使用;如果该对象本身没有这个功能,则去 __proto__ 中找。

1. prototype [显式原型]

 prototype 是一个显式的原型属性,只有函数才拥有该属性。 
   每一个函数在创建之后都会拥有一个名为 prototype 的属性,这个属性指向函数的原型对象。( 通过 Function.prototype.bind 方法构造出来的函数是个例外,它没有 prototype 属性 )

protptype 是一个指针,指向的是一个对象。比如 Array.ptototype 指向的就是 Array 这个函数的原型对象。

函数的原型对象中有constructor和_proto_两个特别的属性

constructor属性指向的就是该函数本身

2. __proto__[隐式原型]

 __proto__ 指向了创建该对象的构造函数的显式原型

打印_proto_属性,发现其指向的是object.prototype,为什么?

因为这个 __proto__.constructor 指向的是 Object

而我们知道:一个函数的原型对象的构造函数是这个函数本身

所以这个 __proto__.constructor 指向的是 Object.prototype.constructor

进而 __proto__ 指向的是 Object.prototype

至于为什么是指向 Object? 因为所有的引用类型默认都是继承 Object 。

作用:

  1. 显式原型:用来实现基于原型的继承与属性的共享。

         2. 隐式原型:构成原型链,同样用于实现基于原型的继承。 举个例子,当我们使用 noWork 这个对象中的 toString() 属性时,在noWork 中找不到,就会沿着 __proto__ 依次查找

3. new 操作符

         当我们使用 new 操作符时,生成的实例对象拥有了 __proto__属性。即在 new 的过程中,新对象被添加了 __proto__ 并且链接到构造函数的原型上。

        new 的过程

  1. 新生成了一个对象,继承对象类的原型,
  2. 执行对象类的构造函数,同时该实例的属性和方法被this引用,即this指向新构造的实例
  3. 新创建的对象由this引用,隐式返回this

     

     我们知道所有对象都可以通过原型链最终找到 Object.prototype ,虽然 Object.prototype 也是一个对象,但是这个对象却不是 Object 创造的,而是引擎自己创建了 Object.prototype 。 所以可以这样说:

     所有实例都是对象,但是对象不一定都是实例。

 接下来我们来看 Function.prototype 这个特殊的对象:

 打印这个对象,会发现这个对象其实是一个函数。我们知道函数都是通过 new Function() 生成的,难道 Function.prototype 也是通过 new Function() 产生的吗?这个函数也是引擎自己创建的。

首先引擎创建了 Object.prototype ,然后创建了 Function.prototype ,并且通过 __proto__ 将两者联系了起来。

 这就是为什么 Function.prototype.bind() 没有 prototype 属性。因为 Function.prototype 是引擎创建出来的对象,引擎认为不需要给这个对象添加 prototype 属性。

 

原型及及原型链使用参考: http://www.cnblogs.com/TomXu/archive/2012/01/05/2305453.html

posted @ 2019-01-17 16:47  煽情小王子  阅读(136)  评论(0)    收藏  举报