• 这些js原型及原型链面试题你能做对几道


    一、前言

    在面试过程中,频频被原型相关知识问住,每次回答都支支吾吾。后来有家非常心仪的公司,在二面时,果不其然,又问原型了!

    我痛下决心用了两天时间钻研了下原型,弄明白后发现世界都明亮了,原来这么简单 ~

    有些理解还比较浅薄,随着时间的推移和理解的深入,以后还会补充。如果大家发现我理解的有问题,欢迎大家在评论中指正。话不多说,切入正题。

    二、构造函数

    讲原型则离不开构造函数,让我们先来认识下构造函数。

    2.1 构造函数分为 实例成员 和 静态成员

    让我们先来看看他们分别是什么样子的。

    实例成员: 实例成员就是在构造函数内部,通过this添加的成员。实例成员只能通过实例化的对象来访问。

    静态成员: 在构造函数本身上添加的成员,只能通过构造函数来访问

        function Star(name,age) {
       
            //实例成员
            this.name = name;
            this.age = age;
        }
        //静态成员
        Star.sex = '女';
    
        let stars = new Star('小红',18);
        console.log(stars);      // Star {name: "小红", age: 18}
        console.log(stars.sex);  // undefined     实例无法访问sex属性
    
        console.log(Star.name); //Star     通过构造函数无法直接访问实例成员
        console.log(Star.sex);  //女       通过构造函数可直接访问静态成员
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.2 通过构造函数创建对象

    该过程也称作实例化

    2.2.1 如何通过构造函数创建一个对象?
     function Father(name) {
       
         this.name = name;
     }
     let son = new Father('Lisa');
     console.log(son); //Father {name: "Lisa"}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    此时,son就是一个新对象。

    2.2.2 new一个新对象的过程,发生了什么?

    (1) 创建一个空对象 son {}
    (2) 为 son 准备原型链连接 son.__proto__ = Father.prototype
    (3) 重新绑定this,使构造函数的this指向新对象 Father.call(this)
    (4) 为新对象属性赋值 son.name
    (5) 返回this return this,此时的新对象就拥有了构造函数的方法和属性了

    2.2.3 每个实例的方法是共享的吗?

    这要看我们如何定义该方法了,分为两种情况。

    方法1:在构造函数上直接定义方法(不共享)
        function Star() {
       
            this.sing = function () {
       
                console.log('我爱唱歌');
            }
        }
        let stu1 = new Star();
        let stu2 = new Star();
        stu1.sing();//我爱唱歌
        stu2.sing();//我爱唱歌
        console.log(stu1.sing === stu2.sing);//false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    很明显,stu1 和 stu2 指向的不是一个地方。
    所以 在构造函数上通过this来添加方法的方式来生成实例,每次生成实例,都是新开辟一个内存空间存方法。这样会导致内存的极大浪费,从而影响性能。

    方法2:通过原型添加方法(共享)

    构造函数通过原型分配的函数,是所有对象共享的。

        function Star(name) {
       
            this.name = name;
        }
        Star.prototype.sing = function () {
       
            console.log('我爱唱歌', this.name);
        };
        let stu1 = new Star('小红');
        let stu2 = new Star('小蓝');
        stu1.sing();//我爱唱歌 小红
        stu2.sing();//我爱唱歌 小蓝
        console.log(stu1.sing === stu2.sing);//true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    2.2.4 实例的属性为基本类型是,它们是共享的吗?

    属性存储的是如果存储的是基本类型,不存在共享问题,是否相同要看值内容。

        let stu1 = new Star('小红');
        let stu2 = new Star('小红');
        console.log(stu1.name === stu2.name);//true
    
        let stu1 = new Star('小红');
        let stu2 = new Star('小蓝');
        console.log(stu1.name === stu2.name);//false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    参考 前端进阶面试题详细解答

    2.2.5 定义构造函数的规则

    公共属性定义到构造函数里面,公共方法我们放到原型对象身上。

    三、原型

    前面我们在 实例化 和 实例共享方法 时,都提到了原型。那么现在聊聊这个神秘的原型到底是什么?

    3.1 什么是原型?

    Father.prototype 就是原型,它是一个对象,我们也称它为原型对象。

    3.2 原型的作用是什么?

    原型的作用,就是共享方法。
    我们通过 Father.prototype.method 可以共享方法,不会反应开辟空间存储方法。

  • 相关阅读:
    MongoDB——将时间戳转换为日期
    【玩转 Cloud Studio】 Cloud Studio的入门教程
    【iOS】—— 循环引用问题
    使用Docker部署Apache Superset并实现公网远程访问
    JavaFx 实现按钮防抖和软件重启(Kotlin)
    openlayers 绘图功能,编辑多边形,长度面积测量,tip提示(八)
    电子学会2022年6月青少年软件编程(图形化)等级考试试卷(二级)答案解析
    安全智能体的前沿技术研究与实践
    音乐信息提取-1-音频表示
    UDP协议
  • 原文地址:https://blog.csdn.net/loveX001/article/details/127858718