04 call、apply、bind
接下来我们来实现一下 apply、call、bind 函数:
注意:我们的实现是练习函数、this、调用关系,不会过度考虑
实现 apply、call、bind
Function.prototype.hycall = function (thisBings, ...args) {
thisBings =
thisBings === null || thisBings === undefined ? window : Object(thisBings)
thisBings.fn = this // 使用 hycall 方法时的函数对象,隐式绑定
var result = thisBings.fn(...args)
delete thisBings.fn
return result
}
Function.prototype.hyapply = function (thisBings, args) {
thisBings = thisBings === null || thisBings === undefined ? window : thisBings
thisBings.fn = this
let result
if (!args) {
result = thisBings.fn()
} else {
result = thisBings.fn(...args)
}
delete thisBings.fn
return result
}
Function.prototype.hybind = function (thisBings, ...bindArgs) {
thisBings = thisBings === null || thisBings === undefined ? window : thisBings
thisBings.fn = this
return function (...newArgs) {
var args = [...bindArgs, ...newArgs]
return thisBings.fn(...args)
}
}
认识 arguments
arguments 是一个 对应于 传递给函数的参数 的 类数组(array-like)对象。
array-like 意味着它不是一个数组类型,而是一个对象类型:
- 但是它却拥有数组的一些特性,比如说 length,比如可以通过 index 索引来访问;
- 但是它却没有数组的一些方法,比如 forEach、map 等;
function foo(num1, num2, num3) {
// 类数组对象中(长的像是一个数组, 本质上是一个对象): arguments
// console.log(arguments)
// 常见的对arguments的操作是三个
// 1.获取参数的长度
console.log(arguments.length)
// 2.根据索引值获取某一个参数
console.log(arguments[2])
console.log(arguments[3])
console.log(arguments[4])
// 3.callee获取当前arguments所在的函数
console.log(arguments.callee)
// arguments.callee()
}
foo(10, 20, 30, 40, 50)
arguments 转成 array
- 自己遍历
function foo(num1, num2) {
var newArr = []
for (var i = 0; i < arguments.length; i++) {
newArr.push(arguments[i])
}
}
foo(10, 20, 30, 40, 50)
- Array.prototype.slice 将 arguments 转成 array
var newArr2 = Array.prototype.slice.call(arguments)
var newArr3 = [].slice.call(arguments)
- ES6 的语法
var newArr4 = Array.from(arguments)
var newArr5 = [...arguments]
额外补充的知识点
Array 中的 slice 实现
Array.prototype.hyslice = function (start, end) {
var arr = this
start = start || 0
end = end || arr.length
var newArray = []
for (var i = start; i < end; i++) {
newArray.push(arr[i])
}
return newArray
}
var newArray = Array.prototype.hyslice.call(['aaaa', 'bbb', 'cccc'], 1, 3)
console.log(newArray)
var newArray2 = ['aaaa', 'bbb', 'cccc'].hyslice(1, 3)
console.log(newArray2)
var names = ['aaa', 'bbb', 'ccc', 'ddd']
console.log(names.slice(1, 3))
箭头函数不绑定 arguments
箭头函数是不绑定 arguments 的,所以我们在箭头函数中使用 arguments 会去上层作用域查找:
- 案例一:
var foo = () => {
console.log(arguments)
}
foo()
- 案例二:
function foo() {
var bar = () => {
console.log(arguments)
}
return bar
}
var fn = foo(123)
fn()
- 案例三:
var foo = (num1, num2, ...args) => {
console.log(args)
}
foo(10, 20, 30, 40, 50)