JavaScript 原型与原型链 ★

51 阅读2分钟

目录

1、原型对象

2、__proto__

3、__proto__ 和 prototype


JavaScript 常被描述为一种基于原型的语言 (prototype-based language) —— 每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为 原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

1、原型对象

在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中 每个函数对象都有一个 prototype 属性,这个属性指向函数的原型对象。每个对象都有 __proto__ 属性,但只有函数对象才有 prototype 属性。

function Person(){}
var person1 = new Person();    //person1是Person的一个实例
Person.prototype = {};         //Person的原型对象

在默认情况下,所有的原型对象都会自动获得一个 constructor(构造函数)属性,该属性指向 prototype 属性所在的函数:Person.prototype.constructor == Person。结论:原型对象(Person.prototype)是构造函数(Person)的一个实例。

那原型对象是用来做什么的?主要作用是用于继承。举个例子:

var Person = function(name){
    this.name = name; // tip: 当函数执行时这个 this 指的是谁?
};
Person.prototype.getName = function(){
    return this.name;  // tip: 当函数执行时这个 this 指的是谁?
}
var person1 = new person('Mick');
person1.name = 'Mick'; // 此时 person1 已经有 name 这个属性了
person1.getName(); //Mick          两次 this 在函数执行时都指向 person1

2、__proto__

JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做 __proto__ 的内置属性,用于指向创建它的构造函数的原型对象person1.__proto__ == Person.prototype

如果不太好理解,可以套用下面这行公式:对象.__proto__ === 其构造函数.prototype 。

3、__proto__ 和 prototype

对象的内部原型(__proto__)和构造器的原型(prototype)的关系:所有函数对象的 __proto__ 都指向 Function.prototype,它是一个空函数(Empty function)。所有对象的 __proto__ 都指向其构造器的 prototype。

function Person(){}
var person1 = new Person();
console.log(person1.__proto__ === Person.prototype); // true
console.log(Person.prototype.__proto__ === Object.prototype) //true
console.log(Object.prototype.__proto__) //null

Person.__proto__ == Function.prototype; //true
console.log(Function.prototype)// function(){} (空函数)

var num = new Array()
console.log(num.__proto__ == Array.prototype) // true
console.log( Array.prototype.__proto__ == Object.prototype) // true
console.log(Array.prototype) // [] (空数组)
console.log(Object.prototype.__proto__) //null

console.log(Array.__proto__ == Function.prototype)// true