JavaScript原型学习记录

150 阅读1分钟

对象

普通对象和函数对象

普通对象

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

supSuper的一个实例,然后我们将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';此时会覆盖原型上的属性