本文介绍JavaScript 语言中 new 关键字调用构造函数的内部执行细节和模拟实现。

在 JavaScript 语言中,我们通过 new 关键字来调用构造函数以创建实例对象,或者是通过 new关键字来调用类以实例化,class是ES6新增的特性,可以理解为它和构造函数是一样的。

在下面的代码中,我们先提供了构造函数Person,然后设置原型对象并创建了实例对象 p。

/* 01-提供构造函数 */
function Person(name, age) {
this.age = age;
this.name = name;
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
}
} /* 02-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
} /* 03-创建实例对象 */
let p = new Person("Yong", 16); /* 04-测试代码 */
console.log(p);
p.showInfo(); /* 打印输出结果:
Person {
age: 16,
name: 'Yong',
showName: [Function],
showAge: [Function]
}
姓名:Yong
年龄:16
*/

构造函数的代码如果换成是Class,那结果也是一样的。这里我们需要关注下当使用 new 关键字 来调用构造函数或者类的时候都做了些什么,也就是内部的实现细节,下面通过代码注释的方式来对这些细节进行说明。

/* 01-提供构造函数 */
function Person(name, age) {
/* [1] 创建空对象 */
/* 模拟:let o = {} */ /* [2] 设置原型对象访问 */
/* 模拟:o.__proto__ = Person.prototype; */ /* [3] 修改 this 指向空对象 */
/* 模拟:this = o */ /* [4] 通过 this 来设置实例属性 */
this.age = age;
this.name = name; /* [5] 通过 this 来设置实例方法 */
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
} /* [6] 默认总是返回内部新创建的对象(this) */
/* 如果主动 return , 若跟的是引用类型则直接返回,值类型则忽略 */
/* 模拟:return this */
} /* 02-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
} /* 03-创建实例对象 */
let p = new Person("Yong", 16);

最后,再花点时间来封装个函数以模拟new 关键字的功能,列出给定代码和测试数据。

/* 01-模拟 new 关键字 */
function mockNew() {
/* [1]-获取构造器 */
/* 说明:arguments类数组执行删除操作,接收删除后的元素 */
let Constructor = [].shift.call(arguments); /* [2]-创建空对象 */
let o = {}; /* [3]-设置新对象的原型指向构造函数的原型对象 */
/* 注意:默认 o.__proto__ 指向的是 Object.prototype */
o.__proto__ = Constructor.prototype; /* [4] 把剩余的参数传递给构造函数(class) */
/* 关键:执行函数Constructor(arguments),并绑定内部的 this */
let instance = Constructor.apply(o, arguments); /* [5] 处理返回值 */
/* 说明:如果是引用类型的数据那么就直接返回,否则总是返回内部新创建的对象 o */
return instance instanceof Object ? instance : o;
} /* 02-提供构造函数(首字母大写区分) */
function Person(name, age) {
this.age = age;
this.name = name;
this.showName = function() {
console.log("姓名:" + this.name);
}
this.showAge = function() {
console.log("年龄:" + this.age);
}
} /* 03-设置原型对象 */
Person.prototype.showInfo = function() {
this.showName();
this.showAge();
} /* 04-测试代码 */
let p1 = mockNew(Person, "Yong", 16);
let p2 = mockNew(Person, "Yi", 18);
console.log(p1, p2);
// Person { age: 16, name: 'Yong', showName: [Function], showAge: [Function] }
// Person { age: 18, name: 'Yi', showName: [Function], showAge: [Function] } p1.showInfo();
/* 姓名:Yong 年龄:16 */

前端开发系列038-基础篇之new关键字的更多相关文章

  1. 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)

    背景 ​ 最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构.代码 ...

  2. 前端开发:css基础知识之盒模型以及浮动布局。

    前端开发:css基础知识之盒模型以及浮动布局 前言 楼主的蛮多朋友最近都在学习html5,他们都会问到同一个问题 浮动是什么东西?  为什么这个浮动没有效果?  这个问题楼主已经回答了n遍.今天则是把 ...

  3. ESP8266开发之旅 基础篇① 走进ESP8266的世界

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  4. ESP8266开发之旅 基础篇② 如何安装ESP8266的Arduino开发环境

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  5. ESP8266开发之旅 基础篇③ ESP8266与Arduino的开发说明

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  6. openlayers5-webpack 入门开发系列一初探篇(附源码下载)

    前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...

  7. leaflet-webpack 入门开发系列一初探篇(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  8. 【Windows10 IoT开发系列】配置篇

    原文:[Windows10 IoT开发系列]配置篇 Windows10 For IoT是Windows 10家族的一个新星,其针对不同平台拥有不同的版本.而其最重要的一个版本是运行在Raspberry ...

  9. ESP8266开发之旅 基础篇④ ESP8266与EEPROM

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

  10. ESP8266开发之旅 基础篇⑥ Ticker——ESP8266定时库

    授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...

随机推荐

  1. zk源码—6.Leader选举的实现原理

    大纲 1.zk是如何实现数据一致性的 (1)数据一致性分析 (2)实现数据一致性的广播模式 (3)实现数据一致性的恢复模式 2.zk是如何进行Leader选举的 (1)服务器启动时的Leader选举 ...

  2. 面试的信心来源于过硬的基础 viewport、跨域、 渲染优化、数组乱序、盒子垂直水平居中、meta、消除transition闪屏、JS 判断设备来源

    原文:面试的信心来源于过硬的基础 在过去的一年很多人不满于公司没有福利.人际关系不好相处.没有发展前途的境遇等等,想着在开年来换一份工作来重新开始自己,那么 你 准备好了吗? 下面是本人整理的一份面试 ...

  3. 可轻便docker部署的密码保存系统:Vaultwarden

    一.简介 Vaultwarden是著名的Bitwarden项目的一个分支,是一个社区驱动的项目,使用Rust语言编写.它是Bitwarden的轻量级自托管替代方案,完全兼容Bitwarden客户端协议 ...

  4. KoalaWiki vs DeepWiki:更优秀的开源代码知识库解决方案

    KoalaWiki vs DeepWiki:更优秀的开源代码知识库解决方案 资源链接: 教程代码仓库:https://github.com/AIDotNet/SemanticKernel.Sample ...

  5. Wan2.1 t2v模型Lora Fine-Tune

    Wan2.1 t2v模型Lora Fine-Tune 1. Wan2.1模型 Wan2.1是由阿里巴巴开源的AI视频生成大模型,具备强大的视觉生成能力,支持文本到视频(T2V)和图像到视频(I2V)任 ...

  6. K8s Service 示例详解

    Kubernetes 官方文档:Services-Networking Service介绍 在kubernetes中,pod是应用程序的载体,我们可以通过pod的ip来访问应用程序,但是pod的ip地 ...

  7. Gin RBAC 权限基础实现

    RBAC (基于角色的访问控制) 是一种广泛应用的权限管理模型, 通过 角色 将 用户 和 权限 解耦, 简化权限分配管理. 用户 (User): 系统的使用者 权限 (Permission): 对资 ...

  8. layUI批量上传文件

    <div class="layui-form-item"> <label class="layui-form-label febs-form-item- ...

  9. docker中源码安装onnx / tvm

    docker安装 可自行到https://tvm.apache.org/docs/install/docker.html 官网下载安装 环境: 系统: ubuntu22.04系统, docker版本: ...

  10. The Eclipse executable launcher was unable to locate its companion shared library

    win10,笔者是安装eclipse2018.03的情况下,想安装java2019EE遇到的路径问题 1.解决方法 找到配置文件 打开,用记事本打开的话会糊成一行,建议用其他方式打开,例如笔者所用的N ...