开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
new做了什么
// 创建构造函数
function Play() {
this.name = name
this.type = type
}
// new一个实例对象
var play = new Play('LOL','game')
typeof Play === 'function' // true
console.log(play) // { name: 'LOL',type: 'game' }
console.log(Object.prototype.toString.call(play)); // [object Object]
上面的代码再熟悉不过了,new是我们常见的一个关键词,那有没有思考过new了之后内部到底干了些什么事情?
这个例子可以看到Play是一个构造函数,一个函数用new操作符来调用后,生成了一个全新的对象。接下来看下控制台输出
console.log(play) // {}
与普通对象相比,play中间还多了一层[[Prototype]],它的constructor是Play这个函数,通过new创建的实例对象最终被[[Prototype]](__proto__)链接到构造函数的Prototype对象上。
play.__proto__ === Play.prototype; // true
再来看看this
function Hero(name){
console.log('赋值前-this', this); // 赋值前-this {}
this.name = name;
console.log('赋值后-this', this); // 赋值后-this {name: '韩信'}
}
var hero = new Hero('韩信');
console.log(hero); // {name: '韩信'}
可以看出Hero函数中的this指向实例hero。
如果函数有返回值怎么处理?
创建实例会返回一个对象,当构造函数内部有返回值的情况还会是对象吗?
function Play(name){
this.name = name;
this.type = type
// 基本类型
// return Null
// return Undefined
// return Number
// return String
// return Boolean
// return Symbol(符号)
返回以上基本类型都会正常返回实例对象
{name:'bsball',type:'sport'}
// 引用类型
// return Object 返回 {}
// return Function
// return Array
// return Date
// return RegExp
// return Error
以上这些值会直接返回这些值
}
var play = new Play('bsball','sport');
console.log(play) // ???
小结
- 通过
new操作符,会创建生成一个全新的对象。- 通过
new创建的实例对象会被执行[[Prototype]](也就是__proto__)链接到构造函数的Prototype对象上。- 通过
new创建的实例对象会绑定到函数调用的this。- 如果函数没有返回引用类型(
Object,Functoin,Array,Date,RegExg,Error),那么new表达式中的函数调用会自动返回这个新创建的对象。
手写new
function rewriteNew(constructor) {
if (typeof constructor !== "function") return
// 基于constructor的原型创建一个全新的对象
let newObj = Object.create(constructor.prototype);
// 获取传入的参数
let args = Array.from(arguments).slice(1);
// 执行constructor函数,获取结果,并将属性添加到新对象newObj上
let result = constructor.apply(newObj, args); // 将this指向newObj
// 判断result类型,如果是object或者function类型,则直接返回结果
let originType = Object.prototype.toString.call(result); // 获取内部属性值
let isObject = originType === '[object Object]';
let isFunction = originType === '[object Function]';
if (isObject || isFunction) {
return result;
} else {
// 如果函数没有返回引用类型,那么`new`表达式中的函数调用会自动返回这个新的对象。
return newObj;
}
}
function Play(name, type){
this.name = name;
this.type = type;
}
Play.prototype.rule = function() {
return this.type
};
var play = rewriteNew(Play, '篮球', 'sport');
console.log(play, play.rule()); // {name: '篮球', type: 'sport'} 'sport'