跳到主要内容

原型与原型链

2024年04月07日
柏拉文
越努力,越幸运

一、认识


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.hasOwnPropertyJavaScript 中唯一一个处理属性但是不查找原型链的函数

二、proto


三、prototype


四、constructor


所有对象内部都会有一个隐式原型__proto__,__proto__指向构造函数的显示原型prototype,prototype 有一个默认属性constructor,指向构造函数。所以所有对象都会继承constructor属性

4.1 数据类型

Number
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);
String
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);
Object
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 原型链解决的是什么问题?

答: 原型链解决的主要是继承问题