js 中,构造函数和普通函数声明没什么区别(唯一的区别就是一些规范吧,比如声明构造函数首字母大写,可以用 this,普通函数首字母小写,通常不用 this 等等),比如一个函数

function Foo(name) {
this.name = name || 'default';
}

可以直接调用,也可以用new关键字来实例化

比如在浏览器直接调用Foo('hello')时候,this 指向的是 window 对象,所以window.name的值为hello

用 new 实例化

var f = new Foo('hello');

那么 this 指向 f,可以通过 f 来获取 name 属性

其实 new 在 js 运行时候做了下面这些事

  1. 新建一个新的对象
  2. 新的对象的__proto__指向构造函数的 prototype
  3. this 指向新的构造函数
  4. 如果构造函数有返回非空对象就返回,否则返回新的对象

根据上面的步骤,我们可以模拟一个 new 功能,完整代码如下

function NewObject(constructor, ...rests) {
var obj = Object.create(constructor.prototype);
// this指向obj
var returnRet = constructor.apply(obj, rests);
var isPrimitive =
returnRet == null ||
(typeof returnRet !== 'object' && typeof returnRet !== 'function');
return isPrimitive ? obj : returnRet;
}
function Foo(name) {
this.name = name || 'default';
}
function NewObject(constructor, ...rests) {
var obj = Object.create(constructor.prototype);
// this指向obj
var returnRet = constructor.apply(obj, rests);
var isPrimitive =
returnRet == null ||
(typeof returnRet !== 'object' && typeof returnRet !== 'function');
return isPrimitive ? obj : returnRet;
}
var a = NewObject(Foo, 'kelen');
var a2 = new Foo('kelen');
console.log(a);
console.log(a2);