为什么从`.bind(...)`获得的函数没有`.prototype`属性?

问题描述 投票:0回答:1

考虑以下创建两个类

Point
YAxisPoint
的用例:

function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function() { 
  return `${this.x},${this.y}`; 
};

var p = new Point(1, 2);
var YAxisPoint = Point.bind(null, 0);
var axisPoint = new YAxisPoint(5);

console.log(p.toString()); // '1,2'
console.log(axisPoint.toString()); // '0,5'

在浏览器中执行此代码会产生正确的结果。现在假设我想重写

toString
构造函数的
YAxisPoint
函数:

YAxisPoint.prototype.toString = function() { return 'override'; }
var newAxisPoint = new YAxisPoint(5);
console.log(newAxisPoint.toString()); // 'override'

在浏览器中执行此代码会产生:

未捕获类型错误:无法设置未定义的属性“toString”

问题1

为什么

YAxisPoint
的原型是未定义的?

我真的不明白。如果我添加以下填充,它将按预期工作。

Function.prototype.bind = function(oThis) {
    if (typeof this !== 'function') {
      // closest thing possible to the ECMAScript 5
      // internal IsCallable function
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }

    var aArgs   = Array.prototype.slice.call(arguments, 1),
        fToBind = this,
        fNOP    = function() {},
        fBound  = function() {
          return fToBind.apply(this instanceof fNOP
                 ? this
                 : oThis,
                 aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      fNOP.prototype = this.prototype; 
    }
    fBound.prototype = new fNOP();

    return fBound;
  };

问题2

浏览器的绑定实现是否存在错误?我在 Opera、Safari、Chrome 和 Firefox 中尝试过,它们都有同样的问题。

这是您可以运行来测试的代码的链接

这个沙箱中的polyfill被注释掉了。您可以取消注释来验证。

javascript bind
1个回答
0
投票

使用

Reflect.construct()
并将
.toString()
设置为
.__proto__
axisPoint

即可达到预期效果

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function() { 
  return `${this.x},${this.y}`; 
};

var p = new Point(1, 2);
var axisPoint = Reflect.construct(Point.bind(null /* Point */, 0), [5]);

console.log(p.toString()); // '1,2'
console.log(axisPoint.toString()); // '0,5'

axisPoint.__proto__.toString = function() { 
  return 'override'; 
}

console.log(axisPoint.toString());

© www.soinside.com 2019 - 2024. All rights reserved.