前端面试当中 js原型及原型链常考知识点

news2025/1/8 21:14:59

一、构造函数

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

1.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);  //女       通过构造函数可直接访问静态成员

2.2 通过构造函数创建对象

该过程也称作实例化

2.2.1 如何通过构造函数创建一个对象?

 function Father(name) {
     this.name = name;
 }
 let son = new Father('Lisa');
 console.log(son); //Father {name: "Lisa"}

此时,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.1 什么是原型?

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

2.2 原型的作用是什么?

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

2.3 原型中this的指向是什么?

原型中this的指向是实例。

三、原型链

3.1 什么是原型链?

原型与原型层层相链接的过程即为原型链。

3.2 原型链应用

对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在
每个对象都有__proto__原型的存在

function Star(name,age) {
    this.name = name;
    this.age = age;
}
Star.prototype.dance = function(){
    console.log('我在跳舞',this.name);
};
let obj = new Star('张萌',18);
console.log(obj.__proto__ === Star.prototype);//true

3.3 原型查找方式

    function Star(name) {
        this.name = name;
        
        (1)首先看obj对象身上是否有dance方法,如果有,则执行对象身上的方法
        this.dance = function () {
            console.log(this.name + '1');
        }
    }
    
    (2)如果没有dance方法,就去构造函数原型对象prototype身上去查找dance这个方法。
    Star.prototype.dance = function () {
        console.log(this.name + '2');
    };
    
    (3)如果再没有dance方法,就去Object原型对象prototype身上去查找dance这个方法。
    Object.prototype.dance = function () {
        console.log(this.name + '3');
    };
    (4)如果再没有,则会报错。
    let obj = new Star('小红');
    obj.dance();

(1)首先看obj对象身上是否有dance方法,如果有,则执行对象身上的方法。

(2)如果没有dance方法,就去构造函数原型对象prototype身上去查找dance这个方法。

(3)如果再没有dance方法,就去Object原型对象prototype身上去查找dance这个方法。

(4)如果再没有,则会报错。

3.4原型的构造器

原型的构造器指向构造函数。

    function Star(name) {
        this.name = name;
    }
    let obj = new Star('小红');
    console.log(Star.prototype.constructor === Star);//true
    console.log(obj.__proto__.constructor === Star); //true

3.4.1 在原型上添加方法需要注意的地方

方法1:构造函数.prototype.方法在原型对象上直接添加方法,此时的原型对象是有constructor构造器的,构造器指向构造函数本身

    function Star(name) {
        this.name = name;
    }
    Star.prototype.dance = function () {
        console.log(this.name);
    };
    let obj = new Star('小红');
    console.log(obj.__proto__);  //{dance: ƒ, constructor: ƒ}
    console.log(obj.__proto__.constructor);  // Star

3.4.2一般不允许直接改变原型prototype指向

改变原型指向,会使原生的方法都没了,所以Array、String这些内置的方法是不允许改变原型指向的。如果改变了,就会报错。

    Array.prototype.getSum = function (arr) {
        let sum = 0;
        for (let i = 0; i < this.length; ++i) {
            sum += this[i];
        }
        return sum;
    };
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    console.log(arr.getSum());//45

如果改变prototype指向,会报错!

    Array.prototype = {
        getSum: function (arr) {
            let sum = 0;
            for (let i = 0; i < this.length; ++i) {
                sum += this[i];
            }
            return sum;
        }
    };
    let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
    console.log(arr.getSum());//45

四.继承 - ES5方法

ES6之前并没有给我们提供extends继承,我们可以通过构造函数+原型对象模拟实现继承。

继承属性,利用call改变this指向。但该方法只可以继承属性,实例不可以使用父类的方法。

    function Father(name) {
        this.name = name;
    }
    Father.prototype.dance = function () {
      console.log('I am dancing');
    };
    function Son(name, age) {
        Father.call(this, name);
        this.age = age;
    }
    let son = new Son('小红', 100);
    son.dance();   //报错

如何继承父类的方法呢?

解决方法1:利用Son.prototype = Father.prototype改变原型指向,但此时我们给子类增加原型方法,同样会影响到父类。

    function Father(name) {
        this.name = name;
    }
    Father.prototype.dance = function () {
        console.log('I am dancing');
    };
    function Son(name, age) {
        Father.call(this, name);
        this.age = age;
    }
    Son.prototype = Father.prototype;
    //为子类添加方法
    Son.prototype.sing = function () {
        console.log('I am singing');
    };
    let son = new Son('小红', 100);
    //此时父类也被影响了
    console.log(Father.prototype) //{dance: ƒ, sing: ƒ, constructor: ƒ}

 解决方法2:子类的原型指向父类的实例,这样就可以顺着原型链共享父类的方法了。并且为子类添加原型方法的时候,不会影响父类。

    function Father(name) {
        this.name = name;
    }
    Father.prototype.dance = function () {
        console.log('I am dancing');
    };
    function Son(name, age) {
        Father.call(this, name);
        this.age = age;
    }
    Son.prototype = new Father();
    Son.prototype.sing = function () {
        console.log('I am singing');
    };
    let son = new Son('小红', 100);
    console.log(Father.prototype) //{dance: ƒ, constructor: ƒ}

五.面试题分享

A.面试题1

Object.prototype.__proto__    //null
Function.prototype.__proto__  //Object.prototype
Object.__proto__              //Function.prototype

讲解: 这里涉及到Function的原型问题,附一张图,这图是一个面试官发给我的,我也不知道原作者在哪里~

B.面试题2

给大家分享那道我被卡住的面试题,希望大家在学习完知识后,可以回顾一下。

按照如下要求实现Person 和 Student 对象
 a)Student 继承Person 
 b)Person 包含一个实例变量 name, 包含一个方法 printName
 c)Student 包含一个实例变量 score, 包含一个实例方法printScore
 d)所有Person和Student对象之间共享一个方法

es6类写法

    class Person {
        constructor(name) {
            this.name = name;
        }
        printName() {
            console.log('This is printName');
        }
        commonMethods(){
            console.log('我是共享方法');
        }
    }

    class Student extends Person {
        constructor(name, score) {
            super(name);
            this.score = score;
        }
        printScore() {
            console.log('This is printScore');
        }
    }

    let stu = new Student('小红');
    let person = new Person('小紫');
    console.log(stu.commonMethods===person.commonMethods);//true

原生写法

    function Person (name){
        this.name = name;
        this.printName=function() {
            console.log('This is printName');
        };
    }
    Person.prototype.commonMethods=function(){
        console.log('我是共享方法');
    };

    function Student(name, score) {
        Person.call(this,name);
        this.score = score;
        this.printScore=function() {
            console.log('This is printScore');
        }
    }
    Student.prototype = new Person();
    let person = new Person('小紫',80);
    let stu = new Student('小红',100);
    console.log(stu.printName===person.printName);//false
    console.log(stu.commonMethods===person.commonMethods);//true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MyBatis】第三篇:传递参数

前面聊了一些配置文件的标签意义&#xff0c;在实例演示的时候&#xff0c;发现用的sql都是定死的&#xff0c;也就是无法传递参数&#xff0c;这个不符合开发的环境的&#xff0c;毕竟程序是需要交互的&#xff0c;自然也会有参数传递&#xff0c;下面依次进行演示。 在映射文…

一个注解(优雅)搞定SpringBoot项目中的身份证号、手机号等敏感数据脱敏

&#x1f4de; 文章简介&#xff1a;一个注解搞定身份证号、手机号等敏感数据脱敏处理 &#x1f4a1; 创作目的&#xff1a;公司中CRM的第一版快封版了&#xff0c;基本功能都落实了。接下来就是预防等保了&#xff0c;我负责的是核心业务客户模块这里自然有很多数据要做脱敏。…

【十 三】Netty 私有协议栈开发

Netty 私有协议栈开发私有协议介绍跨节点通信私有协议栈设计私有协议栈的网络拓扑图协议栈功能描述协议的通信模型消息体定义消息定义表私有协议消息头定义私有协议支持的字段类型私有协议的编解码规范私有协议的编码私有协议的解码链路的建立客户端握手请求握手请求消息定义服…

智能上线阻断的算法和实践

一、背景 上线是引起系统故障的主要原因之一&#xff0c;在有些公司甚至能占到故障原因的一半&#xff0c;及时地发现并阻断、回滚存在故障隐患的上线&#xff0c;可以有效地减少系统故障。 事实上&#xff0c;现在很多平台已经提供了基于手工配置规则来进行变更阻断的能力。…

Modern C++ | 谈谈万能引用以及它的衍生问题:将亡值、引用折叠和完美转发

文章目录前言左右值引用的铺垫万能引用&&引用折叠完美转发前言 在学习Linux系统编程的过程中&#xff0c;想着得到了新知识&#xff0c;不能把旧知识忘了啊&#xff0c;所以我就读起了以前写的博客&#xff0c;在Modern C介绍这篇博客中&#xff0c;关于完美转发只是介…

安科瑞智能仪表在密集母线行业中的应用

安科瑞 华楠AMB100智能母线监控系列系统示意图功能1.电压、电流、频率、有功功率、无功功率、功率因数、有功电能、无功电能、2-63次谐波、温度、湿度、漏电流等电参量测量&#xff1b;2.交流2DI、2DO&#xff0c;直流4DI、2DO&#xff1b;3.可信号取电或者独立辅助电源供电&am…

windows安装VMware最新版本(VMware Workstation 17.0 Pro)详细教程

目录 一、概述 二、下载 VMware Workstation 17.0 Pro 三、安装 VMware Workstation 17.0 Pro 四、创建一个空的虚拟机 一、概述 VMware Workstation Pro™ 是一个运行在window或Linux系统的软件&#xff0c;使开发人员能够在同一台 PC 上同时运行多个基于 x86 的 Windows、Li…

国内最全的Spring Boot系列之六

在新的一年祝大家兔年大吉&#xff0c;兔耳冲天&#xff0c;动如脱兔! 2022年就这么过去了&#xff0c;闭上眼回首2022年发生的事情&#xff0c;犹如过眼云烟 —— 一事无成的感觉。 2022年到底都发生了什么事情&#xff0c;坚持了什么&#xff1f;于是我闭上眼睛&#xff0c…

2023-1-16 刷题情况

子相似性 III 题目描述 一个句子是由一些单词与它们之间的单个空格组成&#xff0c;且句子的开头和结尾没有多余空格。比方说&#xff0c;“Hello World” &#xff0c;“HELLO” &#xff0c;“hello world hello world” 都是句子。每个单词都 只 包含大写和小写英文字母。…

K8s 如何通过 ConfigMap 来配置 Redis ?

1、创建 ConfigMap YAML 配置文件 cat <<EOF >./example-redis-config.yaml apiVersion: v1 kind: ConfigMap metadata:name: example-redis-config data:redis-config: "" EOF2、创建 ConfigMap 资源 kubectl apply -f example-redis-config.yaml创建完成…

VMware 已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作的解决方法

在电脑上安装VMWare&#xff0c;运行虚拟机发现提示无法执行64位操作。本人系统是windows10,64位系统。错误提示&#xff1a; 已将该虚拟机配置为使用 64 位客户机操作系统。但是&#xff0c;无法执行 64 位操作。 此主机支持 Intel VT-x&#xff0c;但 Intel VT-x 处于禁用状态…

HTML的body元素

&#xff08;1&#xff09;HTML的body元素 body是一个简单的HTML稳定最基本的必需元素。 <body> 标签定义文档的主体。 <body> 元素包含文档的所有内容&#xff08;比如文本、超链接、图像、表格和列表等等&#xff09;。 &#xff08;2&#xff09;HTML 网页结…

HTML零基础教程,九大知识点带你玩转前端(上)

博主&#xff1a;冰小九&#xff0c;新人博主一只&#xff0c;欢迎大佬前来指导 冰小九的主页喜欢请给个三连加关注呀&#xff0c;谢谢&#x1f337;&#x1f337;&#x1f337;三连加关注&#xff0c;追文不迷路&#xff0c;你们的支持就是我最大的动力&#xff01;&#xff0…

【自学Docker 】Docker管理命令大全(上)

文章目录Docker create命令Docker create命令概述Docker create命令语法Docker create命令参数列表案例创建容器运行容器Docker create命令总结Docker exec命令Docker exec命令概述Docker exec命令语法Docker exec命令参数列表案例查看文件创建文件进入容器Docker exec命令总结…

Dubbo 自适应SPI

Dubbo 自适应SPI 1. 原理 在 Dubbo 中&#xff0c;很多拓展都是通过 SPI 机制进行加载的&#xff0c;比如 Protocol、Cluster、LoadBalance 等。有时&#xff0c;有些拓展并不想在框架启动阶段被加载&#xff0c;而是希望在拓展方法被调用时&#xff0c;根据运行时参数进行加…

录屏软件无水印免费,分享一款功能强大且免费的录屏软件

市面上多数录屏软件&#xff0c;只能试用版录制几分钟的视频&#xff0c;且带有水印。想要长时间录制电脑屏幕、录制无水印的录屏&#xff0c;需要解锁才可以。那有没有一款录屏软件试用版就能无水印&#xff1f;当然有啦。小编今天给大家分享一款不限制录制时长&#xff0c;且…

springboot整合Freemarker模板引擎

2.2 模板引擎 2.2.1 什么是模板引擎 根据前边的数据模型分析&#xff0c;课程预览就是把课程的相关信息进行整合&#xff0c;在课程预览界面进行展示&#xff0c;课程预览界面与课程发布的课程详情界面一致&#xff0c;保证了教学机构人员发布前看到什么样&#xff0c;发布后…

【Win11 + VSCode配置OpenCV C++一站式开发调试环境教程】

Win11 VSCode配置OpenCV C一站式开发调试环境教程1 下载1.1 版本介绍&#xff1a;1.2 对应三个软件的连接&#xff1a;2 环境配置3 编译1 下载 需要下载三个软件&#xff1a;OpenCV 、MInGW、CMake 1.1 版本介绍&#xff1a; 打开 OpenCV-MinGW-Build&#xff1a;OpenCV-4.…

Android启动流程源码分析(基于Android S)

从上图我们可以清楚的看到Android系统的启动分为以下几个步骤 启动电源以及启动系统 当我们按下电源键时, 引导芯片代码开始从预定义的地方(固化在ROM)开始执行, 加载引导程序到RAM, 然后执行 引导程序 引导程序是在Android操作系统开始运行前的一个小程序. 引导程序是运行的…

图片转PDF怎么弄?这几个方法值得你试一试

PDF是一种特殊的文件格式&#xff0c;它可以在任何设备和平台上进行传输&#xff0c;并且能够保证文件版式不被修改&#xff0c;此外&#xff0c;还可以兼容不同的系统&#xff0c;因为它的这些优势&#xff0c;大多数的人就喜欢将自己编辑好的WORD、PPT、EXCEL、图片等文件转换…