原型与原型链
一、认识
在JavaScript
中是使用构造函数来新建一个对象的,每一个构造函数的内部都有一个显式原型prototype。显式原型prototype包含了由该构造函数创建的所有实例共享的属性和方法。当使用构造函数新建一个对象后,在这个对象的内部将包含一个指针即隐式原型__proto__
,这个指针指向构造函数的显式原型prototype。当访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就是新建的对象为什么能够使用 **toString()**等方法的原因。
由上所述,总结如下几点:
-
引用类型(对象、数组、函数等) 都具有对象特性,可自由扩展属性。
-
引用类型 都具有一个隐式原型
__pro__
,__pro__
指向它的构造函数的显示原型prototype。const obj = {}; // new Object()
console.log(obj.__proto__ === Object.prototype); // true
const array = []; // new Array()
console.log(array.__proto__ === Array.prototype); // true
function foo(){ // new Function()
}
console.log(foo.__proto__ === Function.prototype); // true
function Person(){
this.name = name;
}
const person = new Person('柏拉图');
// person.__proto__ = Person.prototype (person 的构造函数为 Person)
// Person.__proto__ = Function.prototype (Person 的构造函数为 Function) -
函数对象 具有
prototype
显式原型,且只有函数才有prototype属性。prototype
有一个默认的constructor
属性,用于记录实例是由哪个构造函数创建。 -
JavaScript
通过__proto__
和prototype
的合作实现了原型链。当查找一个对象的属性时,JavaScript
会向上遍历原型链(也就是向上遍历__proto__
也就是它的构造函数的显示原型prototype
),直到找到给定名称的属性为止,到查找到达原型链的顶部 - 也就是Object.prototype
- 但是仍然没有找到指定的属性,就会返回 undefined。此时若想避免原型链查找, 建议使用Object.hasOwnProperty
方法. 因为Object.hasOwnProperty
是JavaScript
中唯一一个处理属性但是不查找原型链的函数
二、proto
三、prototype
四、constructor
所有对象内部都会有一个隐式原型__proto__
,__proto__
指向构造函数的显示原型prototype
,prototype
有一个默认属性constructor
,指向构造函数。所以所有对象都会继承constructor
属性
4.1 数据类型
const num = new Number(1);
console.log(num.constructor);
console.log(num.constructor.name);
console.log(num.constructor === Number);
console.log(num.constructor.prototype === Number.prototype);
const str = new String(1);
console.log(str.constructor);
console.log(str.constructor.name);
console.log(str.constructor === String);
console.log(str.constructor.prototype === String.prototype);
const obj = {};
console.log(obj.constructor);
console.log(obj.constructor.name);
console.log(obj.constructor === Object);
console.log(obj.constructor.prototype === Object.prototype);
function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person("柏拉图", 23);
console.log(person.constructor);
console.log(person.constructor.name);
console.log(person.constructor === Person);
console.log(person.constructor.prototype === Person.prototype);
4.2 应用场景
场景一、通过对象.constructor.prototype
判断对象是否为原型
function isPrototypeFun(object) {
const ctor = object && object.constructor;
const proto =
(typeof ctor === "function" && ctor.prototype) || Object.prototype;
return object === proto;
}
五、问题
5.1 原型链解决的是什么问题?
答: 原型链解决的主要是继承问题