专栏首页前端架构JavaScript new 关键词解析及原生实现 new
原创

JavaScript new 关键词解析及原生实现 new

java里面,new 运算符是用来实例化一个类,从而在内存中分配一个实例对象。 但在 javascript 中,原型语言没类,只有对象与原型链继承

JavaScript 中 new 表达式的作用是生成一个对象。

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例

new 关键字会进行如下的操作:

  • 创建一个空对象(即{});
  • 链接该对象(即设置该对象的构造函数)到另一个对象 ;
  • 将步骤1新创建的对象作为this的上下文 ;
  • 如果该函数没有返回对象,则返回this。

根据这个步骤,手工实现new

function create(){
  //创建一个空对象
  let obj = new Object();
  //获取构造函数  // let args = [].slice.call(arguments); let Fun = args.shift();
  let Constructor = [].shift.call(arguments);
  //链接到原型
  obj.__proto__ = Constructor.prototype;
  //绑定this值,使用apply,将构造函数中的this指向新对象,这样新对象就可以访问构造函数中的属性和方法
  let result = Constructor.apply(obj,arguments);
  //返回新对象
  return typeof result === "object" ? result : obj;//如果返回值是一个对象就返回该对象,否则返回构造函数的一个实例对象
}

在javascript中, 通过new可以产生原对象的一个实例对象,而这个实例对象继承了原对象的属性和方法。因此,new存在的意义在于它实现了javascript中的继承

在《JavaScript模式》这本书中,new的过程说的比较直白,当我们new一个构造器,主要有三步: • 创建一个空对象,将它的引用赋给 this,继承函数的原型。 • 通过 this 将属性和方法添加至这个对象 • 最后返回 this 指向的新对象,也就是实例(如果没有手动返回其他的对象)

当我们new一个构造函数,得到的实例继承了构造器的构造属性(this.name这些)以及原型上的属性

// ES5构造函数
let Parent = function (name, age) {
    //1.创建一个新对象,赋予this,这一步是隐性的,
    // let this = {};
    //2.给this指向的对象赋予构造属性
    this.name = name;
    this.age = age;
    //3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
    // return this;  //this的创建与返回是隐性的
};
const child = new Parent();

但上述这个解释我觉得不够完美,它只描述了构造器属性是如何塞给实例,没说原型上的属性是如何给实例继承的。

我在winter大神的重学前端专栏中,看到了比较符合我心意的,同时也是符合原理的描述: • 以构造器的prototype属性为原型,创建新对象; • 将this(也就是上一句中的新对象)和调用参数传给构造器,执行; • 如果构造器没有手动返回对象,则返回第一步创建的新对象,如果有,则舍弃掉第一步创建的新对象,返回手动return的对象。

new过程中会新建对象,此对象会继承构造器的原型与原型上的属性,最后它会被作为实例返回这样一个过程

以直观的方式来理解的话,关键词 new 之后所写的是类名。不过正如此前说明,JavaScript 中没有类的概念,所以,根据 JavaScript 的语法规则,new 之后所写的是函数名。在 new 之后写函数名的话,就会把该函数作为构造函数来进行调用

在 JavaScript 的语言特性中没有“类”的概念,为了便于理解,将用类 这个词来称呼那些可以被视作“类”的概念。来称呼那些实际上将会调 用构造函数的 Function 对象。此外,在强调对象是通过调用构造函数而生成的时候,会将这些被生成的 对象称作对象实例以示区别。

虽然在 JavaScript 中没有类的概念,但将 new 之后所写的标识符(函数名)看作是类名, 也并没有什么概念上的问题。也就是说,完全可以认为,上文中代码 new Object() 的作用是生成一个 Object 类的实例。

对类的功能的整理

接口

说明

函数或是构造函数的调用

-

类的属性

相当于Java 中的static 方法或是static 域

prototype 对象的属性

相当于Java 中的实例方法

实例属性

相当于Java 中的实例域

类的属性是一个类自身的属性,例如,String 类的属性是 String 类的对象自身的属性。如果是函数的话,则可以像 String.fromCharCode(0x41) 这样来使用。如果用更加直观一些的说法来讲,这就相当于 Java 或 C++ 中的 static 方法。

prototype 对象的属性和实例属性,都是以对象实例的形式来进行访问的。以 String 类为例,可以以 str.trim() 或是 str.length 的方式,来使用引用了 String 对象(对象实例)的变量 str。

prototype 对象的属性与实例属性之间的不同点在于是否进行了继承。例如,String 对象的 trim 方法,其实是 String.prototype 对象的属性。这种以实例来继承属性的方式被称为原型继承。

实现一个简单的new方法

//自己定义的new方法
let newMethod = function (Parent, ...rest) {
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    let result = Parent.apply(child, rest);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象
    return typeof result  === 'object' ? result : child;
};

参考文章:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

JavaScript深入之new的模拟实现 https://github.com/mqyqingfeng/Blog/issues/13

js new一个对象的过程,实现一个简单的new方法 https://www.cnblogs.com/echolun/p/10903290.html

js手动实现new方法 https://www.jianshu.com/p/9cee6a703e01

转载本站文章《JavaScript new 关键词解析及原生实现 new 》, 请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2020_0630_8498.html

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

关注作者,阅读全部精彩内容

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 原生JS实现飘浮关键词特效

    分享一个原生JS实现的飘浮关键词的效果,鼠标悬停可让关键词停止运动,点击关键词可跳转到对应的页面,效果如下:

    越陌度阡
  • 《JavaScript 模式》读书笔记(6)— 代码复用模式1

      我们有开始进入新篇章了。这篇内容主要讲代码复用模式,实际上代码复用,就是继承啊,原型啊,构造函数啊等等这一类的内容。对于前端进阶来说,是很重要的基础知识。这...

    zaking
  • 每个JavaScript工程师都应懂的33个概念

    这个项目是为了帮助开发者掌握 JavaScript 概念而创立的。它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南。

    Fundebug
  • 每个JavaScript工程师都应懂的33个概念

    这个项目是为了帮助开发者掌握 JavaScript 概念而创立的。它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南。

    Fundebug
  • 自己动手实现一个简单的JSON解析器

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。相对于另一种数据交换格式 XML,JSON 有着诸多优点。比如易读...

    田小波
  • 自己动手实现一个简单的JSON解析器

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。相对于另一种数据交换格式 XML,JSON 有着诸多优点。比如易读...

    田小波
  • 徒手撸一个JSON解析器

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。相对于另一种数据交换格式 XML,JSON 有着诸多优点。比如易读...

    南风
  • 前端冲刺必备指南-执行上下文/作用域链/闭包/一等公民

    大家好,我是吒儿?,每天努力一点点?,就能升职加薪?当上总经理出任CEO迎娶白富美走上人生巅峰?,想想还有点小激动呢?。

    达达前端
  • 资源 | 十五分钟完成Regex五天任务:FastText,语料库数据快速清理利器

    机器之心
  • 黑科技 | 用Python只花十五分钟完成正则表达式五天任务量

    数据清理是很多机器学习任务上我们遇到的首要问题。本文介绍的 FastText 是一个开源 Python 库,可用于快速进行大规模语料库的文本搜索与替换。该项目的...

    小小科
  • javascript基础修炼(2)——What's this(上)

    this是javascript关键字之一,是javascript能够实现面向对象编程的核心概念。用得好能让代码优雅高端,风骚飘逸,用不好也绝对是坑人坑己利器。我...

    大史不说话
  • this四种绑定方式之间的奇淫技巧

    写在前面 上一篇中,我们对于JavaScript中原始值、复杂值以及内存空间进行了一个深入浅出的总结,这次我们来聊一聊JavaScript中this关键字的深入...

    okaychen
  • 面向对象的JavaScript代码

    人类非常善于将东西归类。编程中有一种数据类型叫对象,就是一种将数据的行为和数据本身归类的方法。这样能帮助设计并理解大段的代码。事实上,面向对象的编程方法在许多程...

    疯狂的技术宅
  • JavaScript的“原型甘露”

    今天跟朋友讨论JS的面向对象编程问题,想起了原来曾经看过一篇文章,但是看过很久想不起来了,用了很多关键词,终于用“悟透JavaScript  面向对象”这两个关...

    用户1177503
  • JavaScript基础回顾一(类型、值和变量)

    没有答对也不要灰心,本文会巩固你的基础知识,后续会有系列的基础回顾知识,以飨诸君!

    Jack Chen
  • javascript异步编程

    简单来说,异步编程就是在执行一个指令之后不是马上得到结果,而是继续执行后面的指令,等到特定的事件触发后,才得到结果。

    OECOM
  • 【精品转载】学习 Vue 源码的必要知识储备

    我最近在写 Vue 进阶的内容。在这个过程中,有些人问我看 Vue 源码需要有哪些准备吗?所以也就有了这篇计划之外的文章。

    用户1462769
  • JavaScript面向对象程序设计—创建对象的模式

    JS本身为我们提供了Array、Date、Math等不少对象(见《浅析JavaScript的对象系统》),但在实际开发中我们使用最多的还是自定义对象。自定义对...

    用户1667431
  • JavaScript面向对象编程-第三版不完全系统解读

    关于JavaScript的百度说法,我们这里就不贴出来了,因为太多了,也找不到标准。烦请大家自行参考,方便自己理解。我们这里只给针对专业权威书籍《Object-...

    老九君

扫码关注云+社区

领取腾讯云代金券