1 2 3 4 5 6 7 8 9 10
| var name = "window"; var test = function() { console.log(this.name); }; test(); var obj = { name: "obj", test: test }; obj.test();
|
设计一个customBind
函数,使其满足如下效果:
1 2 3 4 5
| var obj = { name: "obj", test: test.customBind(window) }; obj.test();
|
很明显customBind
函数需要改变 this 的指向,所以需要用到call
或apply
方法
1 2 3 4 5 6 7 8
| Function.prototype.customBind = function(that) { var _this = this, slice = Array.prototype.slice, args = slice.call(arguments, 1); return function() { return _this.apply(that, args); }; };
|
以上代码可以实现作用域绑定,但是无法支持调用函数的参数传递,也就是说obj.test('obj2')
里传递的参数不会被处理,因此我们需要改进一下customBind
函数:
1 2 3 4 5 6 7 8 9
| Function.prototype.customBind = function(that) { var _this = this, slice = Array.prototype.slice, args = slice.call(arguments, 1); return function() { return _this.apply(that, args.concat(slice.call(arguments, 0))); }; };
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var name = "window"; var test = function(a, b) { console.log("作用域绑定:" + this.name); console.log("customBind传递的参数:" + a); console.log("调用函数传递的参数:" + b); }; var obj = { name: "obj", test: test.customBind(window, "obj") }; obj.test("obj2");
|
测试通过,所以 js 中的 bind 函数可以这样实现:
1 2 3 4 5 6 7 8
| Function.prototype.bind = function(that) { var _this = this, slice = Array.prototype.slice, args = slice.call(arguments, 1); return function() { return _this.apply(that, args.concat(slice.call(arguments, 0))); }; };
|
如果使用ES6的写法会更加简单:
1 2 3 4 5 6
| Function.prototype.bind = function (that, ...arg) { var _this = this return function name(...inArg) { return _this.apply(that, arg.concat(inArg)) } }
|