前端知识体系:JavaScript基础-原型和原型链-new一个对象的详细过程,手动实现一个 new操作符
可以描述 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'
最新文章
- eclipse各版本介绍
- Macaca-iOS入门那些事
- MySQL_财务统计各产品品类各城市上周收入毛利表_20161202
- hdu 4617 Weapon
- 数据库的编码浅谈(ZHS16GBK与US7ASCII)
- Codeforces 161 D. Distance in Tree (树dp)
- 用PYTHON硬写SOCKET
- 深入了解java集群技术
- ubuntu终端命令
- Mac 10.10 下安装jdk 1.7 以上
- 随机采样和随机模拟:吉布斯采样Gibbs Sampling
- ivew ui
- Java多线程之Executor框架和手写简易的线程池
- [SoapUI] 从测试套件,测试用例,测试步骤,测试数据各个级别控制是否执行
- php中 curl, fsockopen ,file_get_contents 三个函数
- .net转PHP从零开始-配置visual studio 2013 PHP开发环境php for visual studio
- SqlServer中循环查询结果集
- 4820: [Sdoi2017]硬币游戏
- 【译】第五篇 Replication:事务复制-How it works
- linux系统安全及应用——账号安全(用户切换与提权)
热门文章
- poj1873(二进制枚举+求凸包周长)
- 数值类型与std::string的相互转换
- python并发编程之多线程(实践篇)
- springcloud断路器Dashboard监控仪表盘的使用
- S03_CH06_AXI_VDMA_OV7725摄像头采集系统
- CTS &; APIO 2019 游记
- Apache2.4+Tomcat7.0整合配置详解
- (三)SpringBoot之配置文件详解:Properties和YAML
- java 框架-缓冲-Redis 2Jedis操作
- default(Nullable(type)) vs default(type)