面试高频:原型链 - prototype & __proto__深入了解

147 阅读3分钟

面试高频:原型链 - prototype & __proto__深入了解

开源

个人开源的leno-admin后台管理项目,前端技术栈:reactHooksant-design;后端技术栈:koamysqlredis,整个项目包含web端electron客户端mob移动端template基础模板,能够满足你快速开发一整套后台管理项目;如果你觉得不错,就为作者点个✨star✨吧,你的支持就是对我最大的鼓励;

演示地址

文档地址

源码github地址

什么是原型?

几乎每个对象JavaScript对象都有另一个与之关联的对象。这另一个对象被称为原型(prototype),第一个对象从这个原型继承属性。
                                                                                   -- 《JavaScript权威指南》

前言

原型链相信是每一个成为前端工程师必须逾越过去的高山,很多专业的书籍讲解的原型链经过翻译之后也是晦涩难懂,初学者很难理解;

故此发表文章,在此简单的梳理下原型链到底是怎样一层关系,最后奉上两道基础的原型链的习题,如若有不对之处,欢迎各位指正;

prototyp与__proto__ 🥬🥬

叫什么?

- prototype  =>  显示原型
- __proto__ =>  隐式原型

特性一

复杂数据类型都有隐式原型__proto__属性:

    const arr = [];
    const obj = [];
    const fun = function () {};

    console.log(arr.__proto__);
    console.log(obj.__proto__);
    console.log(fun.__proto__);

Snipaste_2022-03-20_21-15-46.jpg

特性二

复杂数据类型,都有obje的特性:

const arr = []
const obj = []
const fun = function () {}

arr.v = 11
obj.v = 11
fun.v = 11

console.log(arr.v) // => 11
console.log(obj.v) // => 11
console.log(fun.v) // => 11

这个特性我们在日常代码中几乎每时每刻都存在,奇视arr、fun、RegExp本质上都是对象;

特性三

复杂数据类型的__proto__的属性值指向它的构造函数的prototype的属性值:

    const arr = [];
    const obj = {};
    const fn = function () {};

    console.log(arr.__proto__ === Array.prototype); // => true
    console.log(obj.__proto__ == Object.prototype); // => true
    console.log(fn.__proto__ == Function.prototype); // => true

特性四

当一个对象的某个属性没有时,它会顺着它的__proto__(也是它的构造函数的prototype)里去寻找属性:

const obj = {}

console.log(obj.hasOwnProperty) // => ƒ hasOwnProperty() { [native code] 

obj对象我们并没有给他赋任何值,他身上是没有hasOwnProperty这个属性的,之所以能够打印出来,是因为obj的__proto__属性是从Object.prototype身上取的;

instanceof 🌰🥕

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上;

   function Fun(v) {
      this.v = v;
    }

    let obj = new Fun("11");
    console.log(obj instanceof Fun); // => true
    console.log(obj instanceof Object); // => true

obj instanceof Fun 相等,是因为obj的__proto__ 等于 Fun.prototype;
obj instanceof Object相等,是因为原型链;
console.log(obj.proto === Fun.prototype); // => true
console.log(Fun.prototype.proto === Object.prototype); // => true

原理图 🥝🍎

src=http___upload-images.jianshu.io_upload_images_18924199-e199cfdafc0646da.jpg&refer=http___upload-images.jianshu.webp

习题练习 🍤🦪

案例一

    // 执行后,a.x & b.x 的结果分别是?

    function A(x) {
      this.x = x;
    }
    A.prototype.x = 1;

    function B(x) {
      this.x = x;
    }
    B.prototype = new A();

    let a = new A(2),
      b = new B(3);
    delete b.x;


    console.log(a.x, b.x); // => 2, undefined

案例二

    //  JS 代码输出的是什么?

    function father() {
      this.num = 935;
      this.work = ["read", "write", "listen"];
    }

    function son() {}
    son.prototype = new father();
    let son1 = new son();
    let son2 = new son();
    son1.unm = 17;
    son1.work.pop();
    console.log(son2.num);
    console.log(son2.work);



    console.log(son2.num); // => 935
    console.log(son2.work); // => ['read','write']

总结

原型链其实就是执行一件事的一个过程,就像串联的东西一样,连在一起,贯穿整个原型链;