绑定、借用方式

Binding, borrowing method

你能解释一下区别吗:

var obj = {
  0: "A",
  1: "B",
  2: "C",
  length: 3,
  print: function(){ console.log(this) }
};

//A (borrowing method. No changes in obj): 
[].join.call(obj, "+"); //-> "A+B+C"

//B:
obj.join = [].join.bind(obj); 
obj.join("+"); //-> "A+B+C"
var oj = obj.join;
oj("-"); //-> "A-B-C" (binded to obj)

//C:
obj.j = [].join;
obj.j("++"); //-> "A+B+C"
var j = obj.j;
j("-"); //-> "A-B-C" (it still binded!)

//D:
var join = [].join.bind(obj)
join("+"); //-> "A+B+C"

//E (not working: [] is a new array every time):
[].join.bind(obj);
[].join("+"); //expected: "A+B+C" but I have: ""

//F (Danger!)
Array.prototype.join = [].join.bind(obj);
[].join("+"); //"A+B+C"

请问A和B有区别吗?
B和C有什么区别?
为什么 E 不起作用?

(附加题)请问F后如何解除绑定方法?

Array.prototype.join = [].join.bind(null);
[].join([1,2,3,4],"+"); //-> "ABC"

1)A和B有区别吗

是的,A没有修改评论中提到的obj

2) B和C有区别吗

除了会打印 'A++B++C' 之外,是的。 B 是显式绑定的,而 C 不是,这意味着它可能会丢失上下文。尝试以下操作:

var fn = obj.join
var fn2 = obj.j

console.log(fn('+')) // works
console.log(fn2('+')) // error

3) 为什么 E 不起作用?

[].join.bind(obj);
// ^ this is an array instance
// calling `join.bind(obj)` makes no modification to that array instance or any other
[].join("+"); //expected: "A+B+C" but I have: ""
// ^ this is different array instance, unaffected by the above call

4) 能否解释一下F后如何解除绑定的方法?

您无法取消绑定使用 javascript 的本机 bind 方法绑定的绑定函数。您可以编写自己的不可绑定版本,但这不是本机的一部分 API.

这是一个简单的实现:

function bind(fn, context) {
  var newFn = function () { return fn.call(context, arguments) }
  newFn.unbind = function () { return fn }
  return newFn
}

function checkCtx (a) { console.log(this, a) }
checkCtx(1); // Window, 1
bind(checkCtx, {})(1) // {}, 1
bind(checkCtx, {}).unbind()(1) // Window, 1