可以描述 new一个对象的详细过程,手动实现一个 new操作符

1. new 一个对象的详细过程:(原文地址

首先我们看下new Person输出什么?

var Person = function(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.show = function() {
console.log(this.name, this.age);
};
var p = new Person("bella", 10);
console.log(p);

有属性name, age 和 __proto__

__proto__里面有原型方法show,constructor, __proto__

然后我们再输出构造器Person.prototype:

对比一下,发现p的__proto__的值就是构造函数Person的prototype的属性值。

因此new操作符创建对象可以分为以下四个步骤:

  ① 创建一个空对象;

  ② 链接到原型(将所创建对象的__proto__属性值设为构造函数的prototype属性值);

  ③ 绑定this(构造函数中的this指向新对象并且调用构造函数);

  ④ 返回新对象。

因此上面的过程就可以等同于下面的过程:

var Person = function(name, age) {
this.name = name;
this.age = age;
};
Person.prototype.show = function() {
console.log(this.name, this.age);
};
// var p = new Person("bella", 10);
var p = {};
p.__proto__ = Person.prototype;
Person.call(p, "balle", 10);
console.log(p);

2. 手动实现一个new操作符:(原文地址

要手动实现 new 操作符,就要明白new操作符做了什么事,如 上面 总结的new操作符创建对象的四个步骤。

这样我们就可以实现一个new方法了:

function realizeNew () {
//创建一个新对象
let obj = {};
//获得构造函数
let Con = [].shift.call(arguments);
//链接到原型(给obj这个新生对象的原型指向它的构造函数的原型)
obj.__proto__ = Con.prototype;
//绑定this
let result = Con.apply(obj,arguments);
//确保new出来的是一个对象
return typeof result === "object" ? result : obj
}

[].shift.call(arguments)的作用是将调用realizeNew方法的第一个值拿出来:

我们实现的realizeNew()需要传入的参数是:构造函数 + 属性

首先创建一个新对象,

然后通过 arguments 类数组我们可以知道参数中包含了构造函数以及我们调用create时传入的其他参数,接下来就是要想如何得到其中这个构造函数和其他参数,由于arguments是类数组,没有直接的方法可以供其使用,我们可以有以下两种方法:

  1)Array.form(arguments).shift();转换成数组,使用数组方法shift将第一项弹出

  2)[].shift().call(arguments);通过call()让arguments能够借用shift()方法

绑定this的时候需要注意:

  1)给构造函数传入属性,注意构造函数的this属性;

  2)参数传进Con对obj的属性复制,this要指向obj对象;

  3)在Con内部手动指定函数执行时的this使用call、apply实现

最后需要返回一个对象

测试:

function Person (name,age){
this.name = name;
this.age = age;
this.say = function () {
console.log("I am " + this.name)
}
} //通过new创建构造实例
let person1 = new Person("Curry",18);
console.log(person1.name); //"Curry"
console.log(person1.age); //
person1.say(); //"I am Curry' //通过realize()方法创造实例
let person2 = realizeNew (Person,"Curry",18);
console.log(person2.name); //"Curry"
console.log(person2.age); //
person2.say(); //"I am Curry'

最新文章

  1. eclipse各版本介绍
  2. Macaca-iOS入门那些事
  3. MySQL_财务统计各产品品类各城市上周收入毛利表_20161202
  4. hdu 4617 Weapon
  5. 数据库的编码浅谈(ZHS16GBK与US7ASCII)
  6. Codeforces 161 D. Distance in Tree (树dp)
  7. 用PYTHON硬写SOCKET
  8. 深入了解java集群技术
  9. ubuntu终端命令
  10. Mac 10.10 下安装jdk 1.7 以上
  11. 随机采样和随机模拟:吉布斯采样Gibbs Sampling
  12. ivew ui
  13. Java多线程之Executor框架和手写简易的线程池
  14. [SoapUI] 从测试套件,测试用例,测试步骤,测试数据各个级别控制是否执行
  15. php中 curl, fsockopen ,file_get_contents 三个函数
  16. .net转PHP从零开始-配置visual studio 2013 PHP开发环境php for visual studio
  17. SqlServer中循环查询结果集
  18. 4820: [Sdoi2017]硬币游戏
  19. 【译】第五篇 Replication:事务复制-How it works
  20. linux系统安全及应用——账号安全(用户切换与提权)

热门文章

  1. poj1873(二进制枚举+求凸包周长)
  2. 数值类型与std::string的相互转换
  3. python并发编程之多线程(实践篇)
  4. springcloud断路器Dashboard监控仪表盘的使用
  5. S03_CH06_AXI_VDMA_OV7725摄像头采集系统
  6. CTS & APIO 2019 游记
  7. Apache2.4+Tomcat7.0整合配置详解
  8. (三)SpringBoot之配置文件详解:Properties和YAML
  9. java 框架-缓冲-Redis 2Jedis操作
  10. default(Nullable(type)) vs default(type)