Seasons123 / blog-FE

web前端相关issue is my blog :lollipop:
2 stars 0 forks source link

密圈中一个js问题 #43

Closed Seasons123 closed 6 years ago

Seasons123 commented 6 years ago

1 如何理解a.call.call(b)

Seasons123 commented 6 years ago

讲解一: 首先,call的作用是执行一个函数(这函数就是 call 方法本身的 this),a.call.call 中的 this 明显是 a.call。 再次,call作用可以改变被他执行的函数的 this 为第一个参数,也就是说,a.call被执行了,并且 a.call 的 this 是 b。 最后,还是回到call的第一个作用,执行 a.call 本身的 this,也就是说 a.call 执行了 b

那么,其结果和 b.call() 就是一样的了。

具体可以看看 ecma-262 中对 call 执行的规范:

  1. Assert: F is an ECMAScript function object.
  2. If F’s [[FunctionKind]] internal slot is "classConstructor", throw a TypeError exception.
  3. Let callerContext be the running execution context.
  4. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  5. Assert: calleeContext is now the running execution context.
  6. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  7. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  8. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  9. If result.[[type]] is return, return NormalCompletion(result.[[value]]).
  10. ReturnIfAbrupt(result).
  11. Return NormalCompletion(undefined).
Seasons123 commented 6 years ago

讲解二: 运算符优先级,member access 高于function call. a.call.call(b) 相当于 var x=a.call ;x.call(b)

Seasons123 commented 6 years ago

讲解三: a.call.call(b); //Function.prototype.call.call(b); => b(); a.call(); //a(); b.call(a, 100, 200); //b(100, 200)(this=a) b.call.apply(b, [a, 100, 200]); //Function.prototype.call.apply(b, [a, 100, 200]) => b(100, 200)(this=a)