JavaScript温故而知新——new操做符的实现

首先咱们要知道new 操做符具体作了些什么?数组

  1. 建立一个空对象
  2. 而后让这个空对象的__proto__指向函数的原型prototype
  3. 执行构造函数中的代码,构造函数中的this指向该对象
  4. 若是构造函数有返回值,则以该对象做为返回值。若没有returnreturn了基本类型,则将新对象做为返回值

若是对于原型还不是很了解的话建议先看看:JavaScript温故而知新——原型和原型链bash

先来实现前三点的效果:闭包

function new2() {
    // 新建一个对象
    var obj = new Object(),
    
    // 取得第一个参数,即传入的构造函数。
    // 这里 shift 会修改原数组,所以 arguments 会被去掉第一个参数
    Constructor = [].shift.call(arguments);
    
    // 将 obj 的原型指向构造函数,这样 obj 就能够访问到构造函数原型中的属性了
    obj.__proto__ = Constructor.prototype;
    
    // 使用 apply ,改变构造函数 this 的指向到新建的对象,这样 obj 就能够的访问到构造函数中的属性了
    Constructor.apply(obj, arguments);
    return obj;
};
复制代码

咱们能够作个测试app

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function() {
    console.log('I am' + this.name);
}
var person = new2(Person, 'xiao', '18')

console.log(person.name)    // xiao
console.log(person.age)     // 18
person.sayName();           // I am xiao
复制代码

实现返回值的效果函数

假如构造函数是有返回值,而且返回值是一个对象:post

function Person(name, age) {
    this.skill = 'eat';
    this.age = age;
    return {
        name: name,
        habit: 'sleep'
    }
}
var person = new Person('xiao', '18')

console.log(person.name)    // xiao
console.log(person.habit)     // sleep
console.log(person.skill)    // undefined
console.log(person.age)     //  undefined
复制代码

能够看到实例person中只能访问返回的对象中的属性,说明此时new的返回值为构造函数Person return 出来的对象。测试

假如构造函数的返回值是一个基本类型的值:ui

function Person(name, age) {
    this.skill = 'eat';
    this.age = age;
    return 'hello world'
}
var person = new Person('xiao', '18')

console.log(person.name)    // undefined
console.log(person.habit)     // undefined
console.log(person.skill)    // eat
console.log(person.age)     //  18
复制代码

能够看到实例person能够正常访问构造函数中的属性,说明此时new的返回值为新建立的原型指向构造函数的对象。this

按照上面的结论来完整实现咱们的new2spa

function objectFactory() {

    var obj = new Object(),

    Constructor = [].shift.call(arguments);

    obj.__proto__ = Constructor.prototype;

    var ret = Constructor.apply(obj, arguments);

    // 判断构造函数返回值是否为对象,是的话返回这个对象,不是则正常返回
    return typeof ret === 'object' ? ret : obj;

};
复制代码

结尾

系列文章:

相关文章
相关标签/搜索