JavaScript
常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。
原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
原型
JavaScript
有七种基本类型 String
、 Number
、 Boolean
、 Null
、 Undefined
、 Symbol
、 Object
,前六种为基本数据类型, Object
为引用类型。函数本质上是 Object
类型, Object
继承自己, Function
继承自己,并且相互继承对方,即 Object
和 Function
既是函数也是对象。
console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true
Object
是 Function
的实例,而 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__
向 Student
的 prototype
寻找方法或属性。若 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