Javascript中的原型

2016-03-09

原型

首先可以通过__proto__属性来查看对象的原型是什么,

那么这个对象的原型怎么来的,通过构造函数上的prototype属性来定义,
普通对象是没有prototype属性的

需要特别分清楚的是:一个对象的原型不等于自己的prototype属性,而是等于它的构造函数的prototype属性,很长时间,我对这个概念的理解是混乱的,上代码说明

首先要确定哪些东西是语言定义的,(或者说是说死的,不要问为什么)
prototype

而哪些东西是根据语法规则产生的

Function类型对象:

有prototype属性,他的prototype属性默认是

1
2
constructor: 他自己
__proto__: Object对象

比如:

1
2
3
4
5
6
7
8
9
10
11
function A() {}

// 其实等价于

var A = new Function();

// constructor: A()
// __proto__: Object

// 那么 A.__proto__ === Function.prototype === function() {}
// A.prototype ===

Object对象本身是个Function类型对象,他是有prototype属性的,而prototype属性上挂的属性和方法就会???

1
a.__proto__ === obj.constructor.prototype === A.prototype

Object类型对象 全都是通过构造函数生成的,他是有原型的,但是没有prototype属性

function A() {}

var a = new A();

由于JavaScript的所有对象都是通过构造函数生成的,而所有构造函数都有prototype属性(其实是所有函数都有prototype属性),所以所有对象都有自己的prototype原型对象。

因此,一个对象的属性和方法,有可能是定义它自身上面,也有可能定义在它的原型对象上面。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。

比如,a对象是b对象的原型,b对象是c对象的原型,以此类推。

因为追根溯源,

最源头的对象都是从Object构造函数生成(使用new Object()命令),
所以如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype。
那么,Object.prototype有没有原型呢?
回答可以是有,也可以是没有,
因为Object.prototype的原型是没有任何属性和方法的null。

Object.prototype对象的原型是null,由于null没有任何属性,所以原型链到此为止。

1
2
3
4
Object.getPrototypeOf  ();
var obj = new Object();
 obj.constructor.prototype === Object.getPrototypeOf(obj)
//结果:true

最简单的情况:一个对象的原型是在其构造函数的prototype属性上


妈蛋!!!
好乱啊

从源头开始

说明:根据js的语言标准,浏览器中__proto__代表着这个对象的原型,不要问什么

Object对象

Object对象是一个Function类型对象,也是个构造函数

  • 他的原型是: Object.__proto__: function() {} 所有函数类型的对象的__proto__都是这个
  • 他的prototype属性是: Object.prototype,这是语法定义的,不需要问为什么

[Object.prototype]是个Object类型的对象, 他应该是语言层面的定义,他有什么属性和方法都是说定了的

所以你不能因为他的constructor是Object,然后就说她的构造函数是Object,
所以

1
Object.prototype.__proto__ === Object.prototype // 这是不对的

先要满足语言上的定义,在来说语法规则

所以,Object.prototype对象的原型是null,为什么,没有为什么,就是这样

规则是什么

一个对象的原型是其构造函数的prototype属性

前面说的都是不讲理的话,现在可以好好讲下道理,道理就是上面这句话

1
2
3
4
5
6
7
function A() {}

var a = new A();
var a1 = new A();

a.__proto__ === A.prototype; // true
a1.__proto__ === A.prototype; // true

那么A.prototype是什么,

  • 首先,是个Object类型的对象
  • 他有一个constructor的属性,constructor是A自己
  • 还有一个原型(__proto__),是Object.prototype

这里又不能讲道理了,语言就是这么定的,这个东西和实例对象息息相关


其实A本身也有原型,即A.__proto__ : function() {} ,这里是可以讲道理的

1
2
console.log(A.constructor.prototype); // function() {}
A.__proto__ === A.constructor.prototype; // true

这些实例对象是没什么关系的,任何函数默认都是如此

回到A.prototype,上面说的是默认情况,但是这个对象可以改的

比如为了实现继承:

1
2
3
4
5
6
7
8
9
10
11
function Pa() {}
Pa.prototype.parentMethod = function() {}

function A() {}

A.prototype = Pa.prototype; // 继承Pa的方法
A.prototype.constructor = A; // 把constructor指回A

// 实例对象操作
var a = new A();
a.parentMethod(); // 可以调的起来,说明a继承到了Pa的parentMethod方法

那么A.prototype.constructor.prototype.constructor.prototype.constructor.prototype.constructor.prototype是什么?

因为 A.prototype.constructor === A, 所以上面无论写多少都是A.prototype