深入JavaScript 模拟实现new

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。


例1

function Person(name, age) {
    this.name = name;
    this.age = age;
}
var child = new Person('sam', 18);

new Person() 过程种发生了什么:
(1)创建了一个新对象
(2)这个新对象 的__proto__指向了Person的原型对象。
不懂请看:深入JavaScript 从原型到原型链
(3)将构造函数的作用域赋给新对象(this就指向了这个新对象)

模拟实现new第一版:

var obj = {};	
obj.__proto__ = Person.prototype;
Person.apply(obj, ['sam', 18]);

我们再将其封装到函数里:型如objectFactory(构造函数, 构造函数的形参)

function objectFactory() {
	var obj = {};
	var cons = [].shift.call(arguments);//把arguments[0]抽出来
	obj.__proto__ = cons.prototype;
	cons.apply(obj, arguments);
	return obj;
}

//test
var child = objectFactory(Person, 'sam2', 118);
console.log(child2);

输出:Person {name: “sam2”, age: 118}


例2

function Person1(name) {
  this.name = name;
  // 没有返回值
}

function Person2(name) {
  this.name = name;
  return name;
  // 返回非对象
}

function Person3(name) {
  this.name = name;
  return { a: 1 };
  // 返回对象
}

function Person4(name) {
  this.name = name;
  return null;
  // 返回null
}

var p1 = new Person1("aa");
var p2 = new Person2("bb");
var p3 = new Person3("cc");
var p4 = new Person4("dd");

console.log(p1); // Person1 {name: "aa"}
console.log(p2); // Person2 {name: "bb"}
console.log(p3); // {a: 1}
console.log(p4); // Person4 {name: "dd"}

通过上面我们发现:当使用 new 来创建对象时,如果函数没有返回值 或 返回值是非对象,那么返回的就是构造函数实例后的对象;如果函数return对象,那么返回这个对象。

null不是对象。
期望此处引用一个对象,但又不知道引用什么,这时用null,表空缺.

思路:
① 既然要判断构造函数的返回值类型,很明显从cons.apply(obj, arguments)入手,改为 var result = cons.apply(obj, arguments);
② 先不考虑null的情况,把最后一句改为return typeof result === ‘object’ ? result : obj;
③再考虑null的情况,加一层判断,改为return typeof result === ‘object’ ? result || obj : obj;

模拟实现new第二版:

function objectFactory() {
	var obj = {};
	var cons = [].shift.call(arguments);//把arguments[0]抽出来
	obj.__proto__ = cons.prototype;
	var result = cons.apply(obj, arguments);
	return typeof result === 'object' ? result || obj : obj;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章