对象
普通对象和函数对象
普通对象
var obj = {};
var Person = function(){};
var p = new Person();
console.log(typeof p);//object
obj和p都是普通对象
函数对象
function fun1(){};
var fun2 = function(){};
var fun3 = new Function();
console.log(typeof fun3);//function
Person 函数对象
原型
普通对象和函数对象都有的属性 [[Prototype]] 部分浏览器的实现是 __proto__ 它指向构造函数的原型对象。
ES5中为非标准属性,ES6标准化了
p.__proto__ === Person.prototype
Person.__proto__ === Function.prototype
只有函数对象拥有prototype属性,指向原型对象
Person.prototype
原型对象是一个普通对象,除Function.prototype外,Function.prototype是一个函数对象,但是它没有prototype属性
console.log(typeof Person.prototype);//object
console.log(typeof Function.prototype);//function
console.log(typeof Function.prototype.prototype);//undefine
原型对象默认拥有的一个constructor属性,指向 prototype所在的函数(构造函数)
Person.prototype.constructor === Person
实例的构造函数 指向 原型对象的构造函数(constructor) 指向的 构造函数
p.constructor === Person;
原型链
原型链是对象和对象之间的一种联系,JavaScript继承的实现不是通过类来实现的,而是通过原型链
var Super = function(){}
Super.prototype.name = 'parent';
var sup = new Super();
var Sub = function(){}
Sub.prototype = sup;
var sub = new Sub();
console.log(sub.name)//parent
console.log(sub.type)//undefine
sup是Super的一个实例,然后我们将Sub.prototype指向了sup,当我们创建一个Sub的实例时,会发生如下联系
sub.__proto__ === Sub.prototype
Sub.prototype === sup
sup.__proto__ === Super.prototype
所以当我输出sub.name时,会先在sub上寻找,未找到则会在Sub.prototype上寻找,仍然未找到则会在Sup.prototype上寻找,这样依次向上寻找,知道找到或者找不到为止。
因为对象都是继承自Object,所以寻找的终点是Object.prototype。
Object.prototype.__proto__ === null
如果我们在sub上定义一个name属性sub.name = 'child';此时会覆盖原型上的属性