new的实现

124 阅读2分钟

new的实现

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

举例:

function Person(name, age){
	this.name = name;
    this.age = age;
    this.sex = 'Won'
}
Person.prototype.strength = 60;
Person.prototype.sayYouName = function(){
	console.log('I am' +  this.name);
}
var person = new Person('Tom','12')

console.log(person.name) // Tom
console.log(person.sex) // Won
console.log(person.strength) // 60
console.log(person.sayYouName()) // I am Tom

从以上代码可以看出实例person可以:

  • 返回的是一个对象
  • 访问到Person构造函数里的属性
  • 访问到Person.prototype中的属性和方法

模拟实现第一步

function myNew(){
	// 创建一个新对象
	let obj = new Object(),
    	// 利用shift可以修改原数组的方式,取出arguments第一个参数(传入的构造函数)
    	con = [].shift.call(arguments);
	// 将obj的原型指向构造函数,这样就可以访问构造函数原型中的属性
    obj._proro_ = con.prototype;
    // 利用apply,改变构造函数的this指向,同时obj,可以访问构造函数中的数据性
    con.apply(obj, arguments);
    return obj
}

模拟实现第二步

当构造函数有返回值得时候

例如1:

function Person(name, age){
    this.age = age;
    this.sex = 'Won'
    return {
    	name:name,
        habit:'Kevin'
    }
}

var person = new Person('Tom','12')
console.log(person.name) // Tom
console.log(person.habit) // Kevin
console.log(person.age) // undefined
console.log(person.sex) // undefined

例如2:

function Person(name, age){
    this.age = age;
    this.sex = 'Won'
    return 'hello word'
}

var person = new Person('Tom','12')
console.log(person.name) // undefined
console.log(person.habit) // undefined
console.log(person.age) // 12
console.log(person.sex) // Won

以上代码可以得出结论:

  • 当构造函数中返回一个对象时,实例person中只能访问返回的对象内的属性

  • 当构造函数中返回一个基本类型值时,忽略这段return语句。实例person可以正常访问对象内的属性

根据以上问题,完善我们的代码:

function myNew(){
	// 创建一个新对象
	let obj = new Object(),
    	// 利用shift可以修改原数组的方式,取出arguments第一个参数(传入的构造函数)
    	con = [].shift.call(arguments);
	// 将obj的原型指向构造函数,这样就可以访问构造函数原型中的属性
    obj._proro_ = con.prototype;
    // 利用apply,改变构造函数的this指向,同时obj,可以访问构造函数中的数据性
    let ret = con.apply(obj, arguments);
    return typeof ret === 'object' ? ret : obj;
}
!!! myNew 函数内
let obj = new Object();
obj._proro_ = con.prototype;
可以合并为
let obj = Object.create(con.prototype)


// 优化之后(无参数)
function myNew(){
	let con = [].shift.call(arguments)
	let obj = Object.create(con.prototype)
    let ret = con.apply(obj,arguments)
    return typeof ret === 'object' ? ret : obj;
}

// 优化之后(有参数)
function myNew(fn, ...args){
	let obj = Object.create(fn.prototype)
    let ret = con.apply(obj, ...args)
    return typeof ret === 'object' ? ret : obj;
}