Appearance
call方法内部执行时: 让func函数立即执行,func函数中的this为第一个参数,之后的参数当作实参传递给func函数
apply方法内部执行时: 让func函数立即执行,func函数中的this为第一个参数,第二个参数(数组)当作实参一项项传递给func函数
bind方法内部执行时: func不立即执行, 把传递进来的信息存储起来(闭包) bind执行完返回一个新的函数,把新函数绑定给元素的事件,当事件触发时执行的是新函数 执行新函数时内部调用func, 并修改this和传入参数
js
~(function (proto) {
const isPrimitive = function isPrimitive (target) {
return target == null || !/^(function|object)$/.test(typeof target)
}
const call = function call (context, ...args) {
if (isPrimitive(context)) {
context = context == null
? window
: new Object(context)
}
const key = Symbol('key')
const fn = this
context[key] = fn
const result = context[key](...args)
delete context[key]
return result
}
const apply = function apply (context, args) {
if (isPrimitive(context)) {
context = context == null
? window
: new Object(context)
}
if (isPrimitive(args)) {
if (args == null) {
args = []
} else {
throw new Error('invalid args')
}
} else if (!Array.isArray(args)) {
args = []
}
const key = Symbol('key')
const fn = this
context[key] = fn
const result = context[key](...args)
delete context[key]
return result
}
const bind = function bind (context, ...args1) {
const fn = this
return function proxy (...args2) {
fn.call(context, ...args1, ...args2)
// fn.apply(context, args1.concat(args2))
}
}
proto.call = call
proto.apply = apply
proto.bind = bind
})(Function.prototype)js
function fn () {
console.log(this)
}
// 非严格模式下,不传/undefined/null,this -> window,传其他值 this -> 其他值
// 严格模式下,不传/undefined,this -> undefined,传谁this就是谁,传null,this -> null
fn.call() // this -> window
fn.call(null) // this -> window
// example1
function fn1 () {
console.log(1)
}
function fn2 () {
console.log(2)
}
fn1.call(fn2)
// fn1.call() context -> fn2, this -> fn1, context[key] = this, context[key]() => this(), 只不过函数里的this是fn2
// fn1(), 输出1
fn1.call.call(fn2)
// fn1.call.call(fn2) context -> fn2, this -> fn1.call, context[key] = this, context[key]() => this(), 只不过函数里面this是fn2
// fn1.call() context -> window, this => fn2(上一步确定下来的), context[key] = this, context[key]() => this(), 只不过函数里的this是fn2
// fn2(), 输出2
Function.prototype.call(fn1)
// Function.prototype.call(fn1) context -> fn1, this -> Function.prototype, context[key] = this, context[key]() => this(), 只不过函数里面的this是fn1
// Function.prototype(), 没有任何输出
Function.prototype.call.call(fn1)
// Function.prototype.call.call(fn1) context -> fn1, this -> Function.prototype.call, context[key] = this, context[key]() => this(), 只不过函数里的this是fn1
// Function.prototype.call() context -> window, this -> fn1, context[key] = fn1, context[key]() => this(), 只不过函数里的this是window
// fn1(), 输出1
// 结论
// 一个call,让call左边的函数执行
// 两个及以上call,让最后一个call的第一个参数执行
// 通过apply求数组最大/最小值, this是谁无所谓
const arr = [1, 2, 3]
Math.max.apply(Math, arr) // 3
// 通过apply合并数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
Array.prototype.push.apply(arr1, arr2) // [ 1, 2, 3, 4, 5, 6 ]
// arr1.push.apply(arr1, arr2)
// [].push.apply(arr1, arr2)
// babel
let min = Math.min(...arr) // => var min = Math.min.apply(Math, _toConsumableArray(arr))