new的实现
new操作符的作用过程
在使用new操作符调用函数时,函数内部的[[constructor]]
会被调用,最终返回一个对象。new操作符的作用过程如下:
- 创建一个新对象,将新对象的原型链修正
- 将函数的this指向赋予新对象
- 执行函数
- 默认返回this(即新对象),如果函数显式指定了返回值,且返回值为对象,则返回显式指定的对象,如果返回值不是对象,则按默认返回新对象。
new操作符的实现
function _new(ctor, ...args) {
if (typeof ctor !== 'function') {
throw 'ctor must be function'
}
// 创建新对象,修正原型链
const obj = Object.create(ctor.prototype)
// 将this指向obj,并调用函数
const res = ctor.apply(obj, args)
// 根据函数的调用结果来确定返回值
const isObject = typeof res === 'object' && res !== null
const isFunction = typeof res === 'function'
return isObject || isFunction? res: obj
}
call和apply的实现
call和apply的作用过程
call和apply都是函数的实例方法,在函数调用call和apply的时候,实际上是以指定this值的方式来调用函数,只是call和apply接收参数的方式有所差异,其他的一致。
call的实现
Function.prototype.call = function(context, ...args) {
// 根据是否传入context来确上下文
let context = context || window
// 将要调用的函数绑定到context的属性fn上,以便使用context.fn()调用函数,即指定了函数this值为context
context.fn = this
const res = context.fn(...args)
delete context.fn
return res
}
apply的实现
Function.prototype.apply = function(context, args) {
// 根据是否传入context来确上下文
let context = context || window
// 将要调用的函数绑定到context的属性fn上,以便使用context.fn()调用函数,即指定了函数this值为context
context.fn = this
const res = context.fn(...args)
delete context.fn
return res
}
bind的实现
bind的作用过程
bind方法是函数的实例方法,同样可以改变函数A调用时内部的this指向,只是返回值为函数B。函数B调用时才会真正调用函数A并改变函数A内部的this值。 因此,bind的实现过程中,会使用闭包机制将上下文对象绑定到函数B内部。
bind的实现
Function.prototype.bind = function(context, ...args) {
if (typeof this !== 'function') {
throw 'this must be function'
}
let self = this
const boundFunc = function() {
self.apply(this instanceof self? this: context, args.concat(Array.prototype.slice.call(arguments)))
}
// 原型链也要记录,因为boundFunc可能会被当做构造函数用
if (this.prorotype) {
boundFunc.prototype = this.prototype
}
return boundFunc
}