原型与原型链

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

原型

JavaScript 有七种基本类型 StringNumberBooleanNullUndefinedSymbolObject ,前六种为基本数据类型, Object 为引用类型。函数本质上是 Object 类型, Object 继承自己, Function 继承自己,并且相互继承对方,即 ObjectFunction 既是函数也是对象。

console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true

ObjectFunction 的实例,而 Function 是它自己的实例。

console.log(Function.prototype); // ƒ () { [native code] }
console.log(Object.prototype); // Object

prototype

每个函数对象都会有一个 prototype 属性, prototype 就是调用构造函数所创建的那个实例对象的原型, prototype 可以让所有对象实例共享它所包含的属性和方法。

function Student() {}
Student.prototype = {
    from: "sdust"
}

var stu1 = new Student();
var stu2 = new Student();

console.log(stu1.from) // sdust
console.log(stu2.from) // sdust

JS 中所有的对象,都有一个 __proto__ 属性,指向实例对象的构造函数原型。

__proto__

__proto__ 是原型链查询中实际用到的,它总是指向 prototype ,就是指向构造函数 Student 的原型对象 prototype 。例如实例化的 stu 会使用 __proto__Studentprototype 寻找方法或属性。若 stu 寻找到了调用的方法或属性,则不会使用 __proto__ 寻找原型对象。

constructor

每个原型都有一个 constructor 属性指向关联的构造函数 Student ,实例的 constructor 指向构造函数 Student

function Student() {}
var stu = new Student();

console.log(Student.prototype.constructor === Student) // true
console.log(stu.constructor === Student) // true

原型链

原型链可以简单理解为将原型连成一条链, js 每一次获取对象中的属性都是一次查询过程,如果在自有属性中找不到就会去原型对象中查找,如果原型对象中还查不到,就回去原型对象的原型中查找,也就是按照原型链查找,直到查找到原型链的顶端,也就是 Object 的原型。

function parent() {

    this.parentInfo = "parent";

}

parent.prototype.getParentInfo = function() {

    return this.parentInfo;

};

function child() {

    this.childInfo = "child";

}

parent.prototype.getChildInfo = function() {

    return this.childInfo;

};

child.prototype = new parent();

var instance = new child();

console.log(instance.getChildInfo()); // child
console.log(instance.getParentInfo()); // parent
console.log(instance.parentInfo); // parent
console.log(instance.__proto__ === child.prototype); //true
console.log(instance.__proto__.__proto__ === parent.prototype); //true
console.log(instance.__proto__.__proto__.__proto__ === Object.prototype); //true
console.log(instance.__proto__.__proto__.__proto__.__proto__ === null); //true

// function student(){}
// console.log(student.__proto__ === Function.prototype) // true
// console.log(Function.__proto__ === Function.prototype) // true
// console.log(Object.__proto__ === Function.prototype) // true
// console.log(Object.prototype.__proto__ === null) // true

转载规则

《原型与原型链》Konata 采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可。
  目录