new
关键字
new 关键词的次要作用就是执行一个构造函数、返回一个实例对象。在 new 的过程中,依据构造函数的状况,来确定是否能够承受参数的传递。
function Person(){this.name = 'Jack';}
var p = new Person();
console.log(p.name) // Jack
这段代码做了四件事
- 创立一个新对象;
- 将构造函数的作用域赋给新对象(this 指向新对象);
- 执行构造函数中的代码(为这个新对象增加属性);
- 返回新对象。
function Person(){
this.name = 'Tom';
return {age: 18}
}
var p = new Person();
console.log(p) // {age: 18}
console.log(p.name) // undefined
console.log(p.age) // 18
构造函数最初 return 进去的是一个和 this 无关的对象时,new 命令会间接返回这个新对象,而不是通过 new 执行步骤生成的 this 对象。
function Person(){
this.name = 'Jack';
return 'tom';
}
var p = new Person();
console.log(p) // {name: 'Jack'}
console.log(p.name) // Jack
当构造函数中 return
的不是一个对象时,那么它还是会依据 new
关键词的执行逻辑,生成一个新的对象(绑定了最新 this),最初返回进去
因而 new
关键词执行之后总是会返回一个对象,要么是实例对象,要么是 return 语句指定的对象。
new 的实现
new 被拜访后做的几件事件
- 让实例能够拜访公有属性
- 让实例能够拜访构造函数原型(constructor.prototype) 所在原型链上的属性
- 构造函数返回的是援用数据类型
function _new(contor, ...args) {if (typeof contor !== "function") {throw "contro must be a function"}
// 结构一个 obj 实例对象
let obj = new Object()
// __proto__能够了解为“结构器的原型”,即__proto__===constructor.prototype
obj.__proto__ = Object.create(contor.prototype)
let res = contor.apply(obj, [...args])
let isObj = typeof res === "object" && res !== null;
let isFunction = typeof res === "function"
return isObj || isFunction ? res : obj
}
apply
,call
, bind
这三个函数比拟常见, 扭转 this 指向
func.call(thisArg, param1, param2, ...)
func.apply(thisArg, [param1,param2,...])
func.bind(thisArg, param1, param2, ...)
call,apply 实现
Function.prototype.call = function(context,...args){
let context = context || window;
context.fn = this;
// 立刻执行
let result = eval("context.fn(...args)")
delete context.fn
return result;
}
Function.prototype.apply = function(context,args){
let context = context || window;
context.fn = this;
// 立刻执行
let result = eval("context.fn(...args)")
delete context.fn
return result;
}
Function.prototype.bind = function (context, ...args) {if (typeof this !== "function") {throw new Error("this must be a function")
}
let self = this;
let fbound = function () {self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)))
}
if (this.prototype) {
// 返回的过程中原型链对象上的属性不能失落, 将 this.prototype 下面的属性挂到 fbound 的原型下面
fbound.prototype = Object.create(this.prototype)
}
// 实现 bind 的外围在于要返回一个函数
return fbound
}