重寫Function.prototype.call()方法
阿新 • • 發佈:2021-02-09
技術標籤:JavaScriptJS面試javascriptjs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body >
<script>
/*
* 1. apply 可以執行函式
* 2. apply的第二個引數是一個數組,也是實參列表
* 3. apply的第二個引數如果為物件或者函式,arguments.length 為 0(不報錯)
* 4. apply只、取到第二個引數, 第三個到最後一個引數會被忽略
* 5. apply的第二個引數傳遞 null/undefined 不報錯, arguments.length 為 0
* 6. apply的第二個引數如果為原始值(string、number、boolean)會報錯:
* Uncaught TypeError: CreateListFromArrayLike called on non-object
*/
// array object
function typeOf(value) {
if (value === null) {
return 'null'
}
// ({}).toString.call(value) -> [object Object]
return typeof(value) === 'object' ? {
'[object Object]': 'Object',
'[object Array]': 'Array',
'[object Number]': 'Number',
'[object String]' : 'String',
'[object Boolean]': 'Boolean'
}[({}).toString.call(value)] : typeof(value)
}
Function.prototype.myApply = function(context, args) {
context = Object(context) || window
context.originFn = this
// 如果傳入的引數為原始值型別並且不為function,報錯
if (typeof(args) !== 'object' && typeof(args) !== 'function') {
throw new TypeError('Uncaught TypeError: CreateListFromArrayLike called on non-object')
}
// 如果沒有傳入第二個引數, 直接執行函式
if (!args || typeOf(args) !== 'Array') {
return context.originFn()
}
// 執行函式
// ' + args + ': 可以將實引數組平鋪
var ret = eval('context.originFn(' + args + ')')
// 刪除屬性
delete context.originFn
// 返回函式的執行結果
return ret
}
// 測試重寫後的效果
function test() {
console.log(this, arguments)
}
test.apply({
a: 1,
b: 2
}, [3, 4, 5])
</script>
</body>
</html>