更新:谢谢你们的支持,最近折腾了一个博客官网出来,方便你们系统阅读,后续会有更多内容和更多优化,猛戳这里查看javascript
------ 如下是正文 ------html
new 运算符建立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例。 ——(来自于MDN)前端
举个栗子java
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 个特性webpack
ES6新增 symbol
类型,不可使用 new Symbol()
,由于 symbol
是基本数据类型,每一个从Symbol()
返回的 symbol
值都是惟一的。git
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(...)
执行时,会发生如下事情:github
Foo.prototype
的新对象被建立。Foo
,并将 this
绑定到新建立的对象。new Foo
等同于 new Foo()
,也就是没有指定参数列表,Foo
不带任何参数调用的状况。new
表达式的结果。若是构造函数没有显式返回一个对象,则使用步骤1建立的对象。new
是关键词,不能够直接覆盖。这里使用 create
来模拟实现 new
的效果。web
new
返回一个新对象,经过 obj.__proto__ = Con.prototype
继承构造函数的原型,同时经过 Con.apply(obj, arguments)
调用父构造函数实现继承,获取构造函数上的属性(【进阶3-3期】)。面试
实现代码以下算法
// 初版
function create() {
// 建立一个空的对象
var obj = new Object(),
// 得到构造函数,arguments中去除第一个参数
Con = [].shift.call(arguments);
// 连接到原型,obj 能够访问到构造函数原型中的属性
obj.__proto__ = Con.prototype;
// 绑定 this 实现继承,obj 能够访问到构造函数中的属性
Con.apply(obj, arguments);
// 返回对象
return obj;
};
复制代码
测试一下
// 测试用例
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了。
进阶系列文章汇总以下,内有优质前端资料,以为不错点个star。
我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!