Function.prototype.bind.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. load("test-common.js");
  2. try {
  3. assert(Function.prototype.bind.length === 1);
  4. var charAt = String.prototype.charAt.bind("bar");
  5. assert(charAt(0) + charAt(1) + charAt(2) === "bar");
  6. function getB() {
  7. return this.toUpperCase().charAt(0);
  8. }
  9. assert(getB.bind("bar")() === "B");
  10. function sum(a, b, c) {
  11. return a + b + c;
  12. }
  13. // Arguments should be able to be bound to a function.
  14. var boundSum = sum.bind(null, 10, 5);
  15. assert(isNaN(boundSum()));
  16. assert(boundSum(5) === 20);
  17. assert(boundSum(5, 6, 7) === 20);
  18. // Arguments should be appended to a BoundFunction's bound arguments.
  19. assert(boundSum.bind(null, 5)() === 20);
  20. // A BoundFunction's length property should be adjusted based on the number
  21. // of bound arguments.
  22. assert(sum.length === 3);
  23. assert(boundSum.length === 1);
  24. assert(boundSum.bind(null, 5).length === 0);
  25. assert(boundSum.bind(null, 5, 6, 7, 8).length === 0);
  26. function identity() {
  27. return this;
  28. }
  29. // It should capture the global object if the |this| value is null or undefined.
  30. assert(identity.bind()() === globalThis);
  31. assert(identity.bind(null)() === globalThis);
  32. assert(identity.bind(undefined)() === globalThis);
  33. function Foo() {
  34. assert(identity.bind()() === globalThis);
  35. assert(identity.bind(this)() === this);
  36. }
  37. new Foo();
  38. // Primitive |this| values should be converted to objects.
  39. assert(identity.bind("foo")() instanceof String);
  40. assert(identity.bind(123)() instanceof Number);
  41. assert(identity.bind(true)() instanceof Boolean);
  42. // It should retain |this| values passed to it.
  43. var obj = { foo: "bar" };
  44. assert(identity.bind(obj)() === obj);
  45. // The bound |this| can not be changed once set
  46. assert(identity.bind("foo").bind(123)() instanceof String);
  47. // The bound |this| value should have no effect on a constructor.
  48. function Bar() {
  49. this.x = 3;
  50. this.y = 4;
  51. }
  52. Bar.prototype.baz = "baz";
  53. var BoundBar = Bar.bind({ u: 5, v: 6 });
  54. var bar = new BoundBar();
  55. assert(bar.x === 3);
  56. assert(bar.y === 4);
  57. assert(typeof bar.u === "undefined");
  58. assert(typeof bar.v === "undefined");
  59. // Objects constructed from BoundFunctions should retain the prototype of the original function.
  60. assert(bar.baz === "baz");
  61. // BoundFunctions should not have a prototype property.
  62. assert(typeof BoundBar.prototype === "undefined");
  63. // Function.prototype.bind should not accept non-function values.
  64. assertThrowsError(() => {
  65. Function.prototype.bind.call("foo");
  66. }, {
  67. error: TypeError,
  68. message: "Not a Function object"
  69. });
  70. // A constructor's arguments should be able to be bound.
  71. var Make5 = Number.bind(null, 5);
  72. assert(Make5() === 5);
  73. assert(new Make5().valueOf() === 5);
  74. // FIXME: Uncomment me when strict mode is implemented
  75. // function strictIdentity() {
  76. // return this;
  77. // }
  78. // assert(strictIdentity.bind()() === undefined);
  79. // assert(strictIdentity.bind(null)() === null);
  80. // assert(strictIdentity.bind(undefined)() === undefined);
  81. // })();
  82. // FIXME: Uncomment me when arrow functions have the correct |this| value.
  83. // // Arrow functions can not have their |this| value set.
  84. // assert((() => this).bind("foo")() === globalThis)
  85. console.log("PASS");
  86. } catch (e) {
  87. console.log("FAIL: " + e);
  88. }