new 的用法
function fn(name) {
this.name = name
/**
1.当函数返回一个原始类型的数据时,对p1无影响
return 123
*/
/**
2.当函数返回一个对象时,p1 = {name: '李四'},且无法访问函数原型上的方法
return {
name: '李四'
}
*/
}
// 在函数原型上加一个方法
fn.prototype.getName = function() {
console.log('姓名:' + this.name)
}
// 3.使用new创建一个实例对象后,实例对象可以访问函数里的属性和函数原型上的方法
const p1 = new fn('张三')
p1.getName() // 姓名:张三
p1 // { name: '张三', __proto__:... }
手动实现new
/* 大致思路说明:
现在有一个fn,fn原型上有一个方法。
现在需要实现_new方法,传入参数为fn:
当fn return的是原始属性时,忽略fn返回值,使_new()出来的能访问fn内的属性和方法,即obj;
当fn return的是对象类型时,则使_new()出来的为return值,即ret。
*/
function _new(fn) {
// 先定义一个对象,对象obj继承fn,obj可以访问fn实例上的方法
let obj = {};
obj.__proto__ = fn.prototype;
// Function.apply(),立即执行Function,
// 并将Function的this指向第一个传的参数,后面的作为函数的参数传进去
// 此时obj作为第一个参数传进去,执行fn后,执行this.name = name,即obj.name = name
// 此时obj = { name: '传入的第二个参数', __proto__: ..., getName(){} }
const ret = fn.apply(obj, [...arguments].slice(1));
// 判断fn的返回值,如果是对象类型的数据,则返回res
// 如果不是,则忽略,仍旧返回obj
return ret instanceof Object ? ret : obj;
}
// 验证_new()方法
let p2 = _new(fn, "name");
console.log(p2); // { name: 'name', __proto__: getName(){} }
console.log(p2.getName()); // name