3

代码

var slice = Function.prototype.call.bind(Array.prototype.slice);

slice() 方法返回一个新的数组对象(原数组的浅拷贝),常用于动态解析参数。看过MDN的童鞋,对这行代码不会陌生。MDN上的描述比较官方,下面我们通过对这行代码的知识点的逐一分析来加深理解。

Function.prototype.call

call :临时性的改变一个函数的this。原本函数是谁调用,this就指向谁。call是通过第一个参数,告诉函数本次调用者另有其人,然后接着传入参数:

fun.call(thisArg, arg1, arg2, ...)

测试demo:

function testCall(){console.log(this)}
testCall()
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}
testCall.call({})
//{}
testCall()
//Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window, …}

Function.prototype.bind

bind:创建一个新的函数,新函数的this永久指向第一个参数:

fun.bind(thisArg[, arg1[, arg2[, ...]]])

测试demo:

var t={testBind(){console.log(this)}}
t.testBind()
//{testBind: ƒ}
t.testBind2=t.testBind.bind({x:1})
t.testBind2()
//{x: 1} 虽然调用的还是t,但是this指向的还是bind的
t.testBind()
//{testBind: ƒ, testBind2: ƒ}
t.testBind2===t.testBind
//false

使用bind去创建的新函数的频次并不高,笔者表示从没用到过~
实用一点的是MDN上介绍的偏函数,即使函数预设参数:

//来源MDN
function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

// Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);

var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

var leadingThirtysevenList = list.bind(undefined, 37,38,39,40);
leadingThirtysevenList();//[37, 38, 39, 40]
leadingThirtysevenList(1,2,3);//[37, 38, 39, 40, 1, 2, 3]

另外一个实用的地方就是文章开头写的快捷调用了:

var slice = Function.prototype.call.bind(Array.prototype.slice);

经过前面的了解,我们再来分析下这段代码:
使用bindcall函数的this永久绑定Array.prototype.slice函数,返回一个新的call函数,我们打印一下:

slice
// ƒ call() { [native code] }

slice({length:1})等价于Array.prototype.slice.call({length:1}),也就是说创建的slicecall 函数的一个变体,是call 函数的一个变体,是call 函数的一个变体。所以笔者觉得,从理解角度来看,新创建的函数slice 命名为newCall更便于理解。

总结

乍一看,newCallslice函数有点绕,一经推敲还是很好理解的。由此我们也可以写出来更多的newCall(快捷调用),例如精确类型判断需要用到的toString

var toString=Function.prototype.call.bind(Object.prototype.toString)
toString({})
//"[object Object]"
toString(1)
//"[object Number]"
toString(null)
//"[object Null]"
toString()
//"[object Undefined]"
toString(false)
//"[object Boolean]"
toString(function(){})
//"[object Function]"

MDN文档:

MDN-call
MDN-bind

Chendye
100 声望7 粉丝