简介
存在一种情况比如你想要调用某个对象中的方法,并且该方法中会调用这个对象的某个属性,如果直接调用比如:
1 2 3 4 5 6 7 8
| this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); var retrieveX = module.getX; retrieveX();
|
可以看到retrieveX中this指向全局,因此如果需要这个this指向module则需要使用bind函数将module.getX的this变成module。bind函数可以实现创建一个新函数,并且制定这个新函数的this值。
1 2 3 4 5
| var retrieveX = module.getX;
var boundGetX = retrieveX.bind(module); boundGetX();
|
用法
bind的第一个参数是要指定的this对象,其它都是需要传入的参数:
1
| fun.bind(thisArg[, arg1[, arg2[, …]]])
|
当绑定函数被调用时,thisArg参数会作为原函数运行时的 this 指向。当使用new 操作符调用绑定函数时,该参数无效。
解释
为了解释“当使用new 操作符调用绑定函数时,该参数无效”这句话,咱们先来归纳一下当使用new操作符来调用函数时,会执行的操作:
- 创建(或构造)一个全新的对象。
- 这个新对象会执行[[Prototype]]连接
- 这个新对象会绑定到函数调用的this
- 如果这个函数没有返回其它对象,那么new表达式中的函数调用会自动返回这个新对象。
因为使用new会将新对象绑定到函数调用的this,所以指定的this将不起作用,所以这个参数将无效。
bind函数返回由指定的this值和初始化参数改造的原函数拷贝。
bind 函数在 ECMA-262 第五版才被加入;它可能无法在所有浏览器上运行。你可以部份地在脚本开头加入以下代码,就能使它运作,让不支持的浏览器也能使用 bind() 功能。
polyfill
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| if (!Function.prototype.bind) { Function.prototype.bind = function(oThis) { if (typeof this !== 'function') { throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() { return fToBind.apply(this instanceof fNOP ? this: oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; if (this.prototype) { fNOP.prototype = this.prototype; } fBound.prototype = new fNOP(); return fBound; }; }
|
call函数
1 2 3 4 5
| Function.prototype.call=function(oThis){ oThis.callFun = this; var args = Array.prototype.slice(arguments, 1); oThis.callFun(...args); }
|
1 2 3 4 5 6 7 8
| Array.prototype.myReduce=function(fn, inital){ var arr = this; var res = inital; for(let i=0; i<arr.length; i++){ res=fn(res, arr[i], i, arr); } return res; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| function parseUrl(url){ var str = url.split('?'); if (str.length<2){ return url; } items = str[1].split('&'); var obj={}; items.forEach((item) => { var param = item.split('='); obj[param[0].trim()] = param[1].trim(); }) return obj; }
|