I couldn't fully understand the code below.
if (!Function.prototype.softBind) { Function.prototype.softBind = function(obj) { var fn = this, curried = [].slice.call( arguments, 1 ), bound = function bound() { return fn.apply( (!this || (typeof window !== "undefined" && this === window) || (typeof global !== "undefined" && this === global) ) ? obj : this, curried.concat.apply( curried, arguments ) ); }; bound.prototype = Object.create( fn.prototype ); return bound; }; } function foo() { console.log("name: " + this.name); } var obj = { name: "obj" }, obj2 = { name: "obj2" }, obj3 = { name: "obj3" }; var fooOBJ = foo.softBind( obj ); fooOBJ(); // name: obj obj2.foo = foo.softBind(obj); obj2.foo(); // name: obj2 <---- look!!! fooOBJ.call( obj3 ); // name: obj3 <---- look! setTimeout( obj2.foo, 10 ); // name: obj <---- falls back to soft-binding
- What does [].slice.call(...) do?
- Are the two 'this' referring to the same thing?
- What does bound.prototype = Object.create(fn.prototype) do?
if (!Function.prototype.softBind) { Function.prototype.softBind = function(obj) { var fn = this; console.log("Outer this = "+ fn); var curried = [].slice.call( arguments, 1 ); console.log("Outer curry = "+curried); var bound = function bound() { console.log("Inner this = " + this); console.log("Inner curry = "+curried.concat.apply( curried, arguments )); return fn.apply( (!this || (typeof window !== "undefined" && this === window) || (typeof global !== "undefined" && this === global) ) ? obj : this, curried.concat.apply( curried, arguments ) ); }; bound.prototype = Object.create( fn.prototype ); console.log("return bound"); return bound; }; } function foo(a1, a2) { console.log(a1 + ' ' +a2 + " name: " + this.name); } var obj = { name: "obj" }, obj2 = { name: "obj2" }, obj3 = { name: "obj3" }; var fooOBJ = foo.softBind( obj, 'A1'); fooOBJ('A2'); // name: obj //obj2.foo = foo.softBind(obj, 'A1'); //obj2.foo('A2'); // name: obj2 <---- look!!! //fooOBJ.call( obj3 ); // name: obj3 <---- look!
Outer this = function foo(a1, a2) { console.log(a1 + ' ' +a2 + " name: " + this.name); } Outer curry = A return bound Inner this = [object Object] Inner curry = A,A2 A A2 name: obj2
[].slice.call(arguments, 1)is semantically equal to
arguments.slice(1)except the latter is syntactically incorrect because the variable arguments is not a real array. It's an 'array-like' object.
The outer this refers to the foo function while the inner this refers to the window (global) variable. It's worth noting that by the time foo.softBind(obj) completes execution, the bound() function hasn't been invoked. It's only invoked when the line fooOBJ('A2') is executed.
bound.prototype = Object.create( fn.prototype );copies all the properties of foo to bound, essentially ensuring that after softbind the function foo doesn't lose any properties.
No comments:
Post a Comment