function test(a, b) {
console.log(this, a, b);
}
function test2() {}
test.call(); // window undefined undefined (严格模式下 this 为 undefined)
test.call(undefined, 1, 2); // window 1 2 (严格模式下传入undefined,test中this是undefined)
test.call({
name: 'Lance',
age: 27
}, 1, 2); // obj 1 2
test.call(test2, 1, 2); // test2 1 2
test.call(1, 1, 2); // 1 1 2
test.call(true, 1, 2); // true 1 2
const utilsModule = (function(Function) {
Function.prototype.myCall = function(ctx) {
// 传了 context 上下文就设置上,没传默认 window
// 如果传了,就用 Object 包一下(因为有可能传基本类型的值)
ctx = ctx ? Object(ctx) : window;
// 函数谁调用,this指向谁,那我们就把当前this(函数本身)挂载到 ctx 上
ctx.originFn = this;
// 从第二个参数开始,都是函数本身要接收的参数了,收集起来
var args = [];
for (var i = 1; i < arguments.length; i++) {
args.push('arguments[' + i + ']');
}
// 使用 eval 执行函数
var ret = eval('ctx.originFn(' + args + ')');
// 删除临时方法 originFn
delete ctx.originFn;
return ret;
}
})(Function);
export default utilsModule;
使用:
<!DOCTYPE html>
<html lang="en">
<body>
<script type="module">
import utilsModule from './index.js'
function test(a, b) {
console.log(this, a, b);
}
function test2() {}
test.myCall(undefined, 1, 2); // window 1 2
test.myCall({
name: 'Lance',
age: 27
}, 1, 2); // obj 1 2
test.myCall(test2, 1, 2); // test2 1 2
test.myCall(1, 1, 2); // 1 1 2
test.myCall(true, 1, 2); // true 1 2
</script>
</body>
</html>
function test(a, b) {
console.log(this, a, b);
}
function test2() {}
test.apply(undefined, [1, 2]); // undefined 1 2
test.apply({
name: 'Lance',
age: 27
}, [1, 2]); // obj 1 2
test.apply(test2, [1, 2]); // test2 1 2
test.apply(1, [1, 2]); // 1 1 2
test.apply(1, null); // 1 undefined undefined
test.apply(1, undefined); // 1 undefined undefined
test.apply(1, function() {}); // 1 undefined undefined
test.apply(1, {}); // 1 undefined undefined
test.apply(1, 1); // Uncaught TypeError: CreateListFromArrayLike called on non-object