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

JavaScript new 关键词解析及原生实现 new的更多相关文章

  1. [转]javascript eval函数解析json数据时为什加上圆括号eval("("+data+")")

    javascript eval函数解析json数据时为什么 加上圆括号?为什么要 eval这里要添加 “("("+data+")");//”呢?   原因在于: ...

  2. JavaScript运行原理解析

    原文:1.http://blog.csdn.net/liaodehong/article/details/50488098 2.Stack的三种含义 (阮一峰) 3. http://lib.csdn. ...

  3. [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析

    [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...

  4. 异类的Javascript处理和解析URL的方式

    通常来说,我们使用Javascript处理和解析URL是使用location对象.在今天这个代码小技巧中,我们使用另外一个比较异类的方式处理和解析URL. 代码如下: function parseUR ...

  5. async和await关键词用于定义原生的协程

    #python为了将语义变得更加明确,就引入了async和await关键词用于定义原生的协程 # async def downloader(url): # return "xxxx" ...

  6. 松软科技Web课堂:JavaScript this 关键词

    实例 var person = { firstName: "Bill", lastName : "Gates", id : 678, fullName : fu ...

  7. Javascript面试题解析

    Javascript的一些面试题让很多同学感到头疼,下面就根据兄弟连教育 )毕业学员面试遇到的面试题,给大家做一个简单的分享,希望对初入职场的你们有一些帮助:Javascript面试题解析. 第一题 ...

  8. 44个 Javascript 变态题解析 (下)

    承接上篇 44个 Javascript 变态题解析 (上) 第23题 [1 < 2 < 3, 3 < 2 < 1] 这个题也还可以. 这个题会让人误以为是 2 > 1 & ...

  9. JavaScript this 关键词

    this是什么呢? JavaScript this 关键词指的是它所属的对象. 它拥有不同的值,具体取决于它所使用的位置: 在方法中,this 指的是所有者对象. 单独的情况下,this 指的是全局对 ...

随机推荐

  1. 3、oracle表空间及索引操作

    3.1.创建表空间和用户授权: 1.创建表空间: CREATE TABLESPACE <表空间名> LOGGING DATAFILE '<存放路径>' SIZE 50M AUT ...

  2. webpack(4)webpack.config.js配置和package.json配置

    前言 上一篇文章我们使用webpack打包成功了,但是每次都要自己手动输入打包的文件地址和打包到哪里去的地址,非常麻烦,所以这里介绍使用配置文件进行打包 webpack.config.js 首先我们创 ...

  3. 『学了就忘』Linux基础 — 1、UNIX系统介绍

    目录 (一)UNIX系统介绍 1.UNIX系统发展历史 2.UNIX 主要发行版本 (二)GNU计划 1.GNU计划介绍 2.为何Stallman会发起这个GNU计划呢? 3.GNU的通用公共许可证: ...

  4. Bootstrap-table 显示行号

    趁热打铁,使用bootstrap-table时,想要显示每行的行号,再网上查了查,网上给的显示行号的大部分方法,只要一翻页,行号就会又从1开始计算, 也许没有碰到想要的,自己试着解决了这个问题,本人初 ...

  5. Leetcode No.136 Single Number(c++实现)

    1. 题目 1.1 英文题目 Given a non-empty array of integers nums, every element appears twice except for one. ...

  6. STM32学习进程

    新建一个自己的工程模板,以我所用的MDK4为例 MDK4软件图标 (1)新建一个自己储存数据的文件夹.以我自己为例(文件夹名字任取自己记住熟悉就行,以下将以我的文件夹文件进行操作讲解) 新建的总体文件 ...

  7. PYTHON IDLE同时运行两个PY,互不影响

    1.打开指定文件夹 2.右击a1.py,用IDLE打开(idle1) 3.右击a2.py,用IDLE打开(idle2) 4.则分别按F5运行,则两个互不影响. 5.再用IDLE1打开新程序,用IDLE ...

  8. AcWing 1086. 恨7不成妻(【代码简洁】标准记忆化搜索+超详解!!)

    看到这题用循环写的dp代码瑟瑟发抖~ 数位dp一般记忆化搜索的写法思维难度较低,也比较常用,这题的简洁代码应该就可以显现出其优越性 (用时4ms,可能比用循环写的dp还要快) 那这里补充一下记忆化搜索 ...

  9. python爬取北京政府信件信息02

    在爬取详细信息页面中,又遇到了问题,就是标签内的信息爬取,用re的正则表达式没有找到解决办法,只能又去网上搜索解决办法 用bs4来解决,用 soup = BeautifulSoup(text,&quo ...

  10. File类与常用IO流第三章IO流概述

    一:以内存为基准,按照数据的流动方向,流向内存为输入(读取数据),流出内存为输出.IO流有四大顶级父类: IO流四大顶级父类   输入流 输出流 字节流 字节输入流 InputStream 字节输出流 ...