new 运算符建立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例。 ——(来自于MDN)
举个栗子javascript
function Car(color) { this.color = color; } Car.prototype.start = function() { console.log(this.color + " car start"); } var car = new Car("black"); car.color; // 访问构造函数里的属性 // black car.start(); // 访问原型里的属性 // black car start
能够看出 new
建立的实例有如下 2 个特性html
ES6新增 symbol
类型,不可使用 new Symbol()
,由于 symbol
是基本数据类型,每一个从Symbol()
返回的 symbol
值都是惟一的。前端
Number("123"); // 123 String(123); // "123" Boolean(123); // true Symbol(123); // Symbol(123) new Number("123"); // Number {123} new String(123); // String {"123"} new Boolean(true); // Boolean {true} new Symbol(123); // Symbol is not a constructor
当代码 new Foo(...)
执行时,会发生如下事情:java
Foo.prototype
的新对象被建立。Foo
,并将 this
绑定到新建立的对象。new Foo
等同于 new Foo()
,也就是没有指定参数列表,Foo
不带任何参数调用的状况。new
表达式的结果。若是构造函数没有显式返回一个对象,则使用步骤1建立的对象。new
是关键词,不能够直接覆盖。这里使用 create
来模拟实现 new
的效果。webpack
new
返回一个新对象,经过 obj.__proto__ = Con.prototype
继承构造函数的原型,同时经过 Con.apply(obj, arguments)
调用父构造函数实现继承,获取构造函数上的属性(【进阶3-3期】)。git
实现代码以下github
// 初版 function create() { // 建立一个空的对象 var obj = new Object(), // 得到构造函数,arguments中去除第一个参数 Con = [].shift.call(arguments); // 连接到原型,obj 能够访问到构造函数原型中的属性 obj.__proto__ = Con.prototype; // 绑定 this 实现继承,obj 能够访问到构造函数中的属性 Con.apply(obj, arguments); // 返回对象 return obj; };
测试一下web
// 测试用例 function Car(color) { this.color = color; } Car.prototype.start = function() { console.log(this.color + " car start"); } var car = create(Car, "black"); car.color; // black car.start(); // black car start
完美!面试
不熟悉 apply / call
的点击查看:【进阶3-3期】深度解析 call 和 apply 原理、使用场景及实现算法
不熟悉继承的点击查看:JavaScript经常使用八种继承方案
上面的代码已经实现了 80%,如今继续优化。
构造函数返回值有以下三种状况:
return
,即返回 undefined
undefined
之外的基本类型状况1:返回一个对象
function Car(color, name) { this.color = color; return { name: name } } var car = new Car("black", "BMW"); car.color; // undefined car.name; // "BMW"
实例 car
中只能访问到返回对象中的属性。
状况2:没有 return
,即返回 undefined
function Car(color, name) { this.color = color; } var car = new Car("black", "BMW"); car.color; // black car.name; // undefined
实例 car
中只能访问到构造函数中的属性,和状况1彻底相反。
状况3:返回undefined
之外的基本类型
function Car(color, name) { this.color = color; return "new car"; } var car = new Car("black", "BMW"); car.color; // black car.name; // undefined
实例 car
中只能访问到构造函数中的属性,和状况1彻底相反,结果至关于没有返回值。
因此须要判断下返回的值是否是一个对象,若是是对象则返回这个对象,否则返回新建立的 obj
对象。
因此实现代码以下:
// 第二版 function create() { // 建立一个空的对象 var obj = new Object(), // 得到构造函数,arguments中去除第一个参数 Con = [].shift.call(arguments); // 连接到原型,obj 能够访问到构造函数原型中的属性 obj.__proto__ = Con.prototype; // 绑定 this 实现继承,obj 能够访问到构造函数中的属性 var ret = Con.apply(obj, arguments); // 优先返回构造函数返回的对象 return ret instanceof Object ? ret : obj; };
问题:用 JS 实现一个无限累加的函数 add
,示例以下:
add(1); // 1 add(1)(2); // 3 add(1)(2)(3); // 6 add(1)(2)(3)(4); // 10 // 以此类推
实现:
function add(a) { function sum(b) { // 使用闭包 a = a + b; // 累加 return sum; } sum.toString = function() { // 重写toString()方法 return a; } return sum; // 返回一个函数 } add(1); // 1 add(1)(2); // 3 add(1)(2)(3); // 6 add(1)(2)(3)(4); // 10
咱们知道打印函数时会自动调用 toString()
方法,函数 add(a)
返回一个闭包 sum(b)
,函数 sum()
中累加计算 a = a + b
,只须要重写sum.toString()
方法返回变量 a
就OK了。
JavaScript 深刻之 new 的模拟实现
进阶系列文章汇总以下,内有优质前端资料,以为不错点个star。
https://github.com/yygmind/blog
我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!