【问题标题】:Can’t move a method that uses super无法移动使用 super 的方法
【发布时间】:2019-03-15 16:24:25
【问题描述】:

我正在阅读this book。查看“15.6.4.2 陷阱:使用 super 的方法无法移动

部分

它说明了以下内容

你不能移动一个使用 super 的方法:这样的方法有 内部插槽 [[HomeObject]] 将其与创建的对象联系起来 in. 如果通过赋值移动它,它将继续引用 原始对象的超属性。

所以,我尝试用不同的对象调用它,也将实例方法分配给不同的对象,但它似乎不起作用。它指的是新对象的属性。大概,作者的意思我没听懂。那么,有人可以举个例子吗?

她是small demo 和下面的代码

class A {
  get a() {
    return 1;
  }

  sayHi() {
    console.log(this.a)
  }
}

class B extends A {
  sayHi() {
    super.sayHi();
  };
}
var obj = {
  a: 4
};
let b = new B();
b.sayHi();
// logs 1

b.sayHi.call(obj);
// logs 4

obj.sayHi = b.sayHi;
obj.sayHi();
// logs 4

【问题讨论】:

    标签: javascript ecmascript-6 es6-class


    【解决方案1】:

    OP 是说super.sayHi() 将始终调用A.prototype.sayHi,无论您调用该方法的对象是什么。人们可能已经预料到了

    const sayHi = new B().sayHi; // or B.prototype.sayHi
    
    const prototype = {
      sayHi() {
        console.log("not the a property");
      }
    };
    const myObject = Object.assign(Object.create(prototype), {
      a: "the a property"
    });
    myObject.sayHi = sayHi;
    myObject.sayHi();
    // or just sayHi.call(myObject);
    

    不记录a 属性- 通过myObject 的原型链调用prototype.sayHi。但事实并非如此,它会正常记录 a 属性。

    【讨论】:

    • 那么为什么它会正常记录a 属性?是否已在较新版本的 EcmaScript 中修复?
    • @MaxWizardK 不,super 自从它在 ES6 中的化身以来总是这样工作?
    • 好的,那么作者在书中所说的“如果你通过赋值移动它,它将继续引用原始对象的超属性”是什么意思。 ?
    • @MaxWizardK 正是我通过call 所做的——查看编辑
    【解决方案2】:

    你的代码没问题,因为当你移动一个方法时this 可以工作,但super 不行(而且你的代码只真正测试this)。以下代码测试super

    class Bird {
      getName() {
        return 'Bird';
      }
    }
    class Mammal {
      getName() {
        return 'Mammal';
      }
    }
    class Human extends Mammal {
      getName() {
        return super.getName();
      }
    }
    class Duck extends Bird {
    }
    // Moving method .getName() from Human.prototype to Duck.prototype
    Duck.prototype.getName = Human.prototype.getName;
    
    console.log(new Duck().getName()); // 'Mammal' (not 'Bird')
    

    要了解结果,您需要了解super 的工作原理——它使用存储在方法本身中的内部属性[[HomeObject]],它不依赖于this。也就是说,Human.prototype.getName() 在内部工作如下:

    Human.prototype.getName = Object.assign(
      function me() {
        return me.__HomeObject__.__proto__.getName();
      },
      { __HomeObject__: Human.prototype }
    );
    

    更多细节在book中解释:

    【讨论】:

    • OP 正在阅读那本书,但不明白“移动方法”是什么意思,也不明白为什么会出现不同的结果
    猜你喜欢
    • 1970-01-01
    • 2016-02-13
    • 2019-03-30
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多