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. 5、could not start the service mysql

    1.这个原因是因为mysql多次安装没有卸载干净的原因; 2.解决办法是: (1)删除系统中已经安装的mysql目录中的内容: (2)同时按住"win+r"键调出"运行& ...

  2. 企业管理CRM不只是客户录入系统

    企业在举办营销活动或者展会之后,将会收集到大量的客户信息,将这些信息有效地整理.完善.储存也是一个不小的工程.如果您的企业经常面遇到这样的情况,不妨使用Zoho CRM系统来帮您完成.但是,Zoho ...

  3. 获取 Windows 密码「GitHub 热点速览 v.21.28」

    作者:HelloGitHub-小鱼干 安全问题一直是 GitHub 的一大热点,因为数据安全问题诞生的各类自托管服务便是.而本周周榜上的 2 个和安全主题相关的项目,有些不同.mimikatz 是个老 ...

  4. 苦B程序员的数据验证之路

    发生了什么事 在一次苦B程序员和苦C程序员的结对编程中发生的一段对话 代码是这样的: public void deleteAllExtendAclsFromContent(String content ...

  5. MySQL 删除devices表中id最大的一行

    原想法:delete from devices where id in (select max(id) from devices); 报错:ERROR 1093 (HY000): You can't ...

  6. php+swoole多线程的操作

    多个任务同时执行 比如,我们要对已知的用户数据进行判断,是否需要发送邮件和短信,如果需要发送则发送. 不使用多进程时,我们首先判断是否发送邮件,如果需要则发送:然后再判断是否需要发送短信,如果需要则发 ...

  7. C语言:scanf()

    #include <stdio.h> int main() { int a;float b; scanf("a=%d,b=%f",&a,&b); pri ...

  8. MQTT 1——物联网集成项目技术选型与说明

    最近做的JAVA项目与物联网设备有集成,记录一下从技术选型到实现,整合: 1.通信协议技术选型,MQTT技术介绍2.MQTT服务端安装,客户端测试3.MQTT客户端与Spring MVC整合 1.项目 ...

  9. 测试笔记01-Git

    Git工具 Git 一个分布式版本管理工具, 学习资料: https://www.liaoxuefeng.com/wiki/896043488029600/1317161920364578 其中:解决 ...

  10. 在Java中,负数的绝对值竟然不一定是正数!!!

    绝对值是指一个数在数轴上所对应点到原点的距离,所以,在数学领域,正数的绝对值是这个数本身,负数的绝对值应该是他的相反数. 这几乎是每个人都知道的. 在Java中,想要获得有个数字的绝对值,可以使用ja ...