Function.prototype.bind.js 3.8 KB

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