最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - ES6 arrow functions trigger "'super' outside of function or class" error - Stack

programmeradmin11浏览0评论

Consider the following super class and sub class extending it:

class SuperClass {
    constructor(name){
        this.name = name;
    }

    sayName = () => {
        alert(this.name);
    }
}

class SubClass extends SuperClass {
    constructor(name){
        super(name);
    }

    sayName = () => {
        super.sayName();
        document.getElementsByTagName('body')[0].innerHTML = this.name;
    }
}

let B = new SubClass('Noam Chomsky');
B.sayName();

In this example the function sayName is written as an arrow function in both class definitions. And when I call B.sayName() I get an error saying:

'super' outside of function or class

JSFiddle demonstrating the error (Check the console)


However, if I re-write the class definitions to not use arrow functions, everything works fine and I do not get an error:

class SuperClass {
    constructor(name){
        this.name = name;
    }

    sayName() {
        alert(this.name);
    }
}

class SubClass extends SuperClass {
    constructor(name){
        super(name);
    }

    sayName() {
        super.sayName();
        document.getElementsByTagName('body')[0].innerHTML = this.name;
    }
}

let B = new SubClass('Noam Chomsky');
B.sayName();

JSFiddle demonstrating that it works fine

Can someone explain why I'm getting this error when I use arrow functions here?

Consider the following super class and sub class extending it:

class SuperClass {
    constructor(name){
        this.name = name;
    }

    sayName = () => {
        alert(this.name);
    }
}

class SubClass extends SuperClass {
    constructor(name){
        super(name);
    }

    sayName = () => {
        super.sayName();
        document.getElementsByTagName('body')[0].innerHTML = this.name;
    }
}

let B = new SubClass('Noam Chomsky');
B.sayName();

In this example the function sayName is written as an arrow function in both class definitions. And when I call B.sayName() I get an error saying:

'super' outside of function or class

JSFiddle demonstrating the error (Check the console)


However, if I re-write the class definitions to not use arrow functions, everything works fine and I do not get an error:

class SuperClass {
    constructor(name){
        this.name = name;
    }

    sayName() {
        alert(this.name);
    }
}

class SubClass extends SuperClass {
    constructor(name){
        super(name);
    }

    sayName() {
        super.sayName();
        document.getElementsByTagName('body')[0].innerHTML = this.name;
    }
}

let B = new SubClass('Noam Chomsky');
B.sayName();

JSFiddle demonstrating that it works fine

Can someone explain why I'm getting this error when I use arrow functions here?

Share Improve this question edited Oct 22, 2017 at 0:56 o01 asked Oct 22, 2017 at 0:51 o01o01 5,45012 gold badges48 silver badges87 bronze badges 4
  • why do you want to define sayName as an arrow function in the first place? sayName = () => { alert(this.name); } syntax is not even standard yet (it's currently stage 2) – Jaromanda X Commented Oct 22, 2017 at 2:42
  • 2 There might be an issue with the Babel version jsfiddle is using. As one of the answers said, calling super.sayName() wouldn't work anyway because there is no sayName method on SuperClass.prototype. However, referencing super inside the SubClass' sayName method should work. After all, the code is the same as (note that I made sayName a proper method in SuperClass): jsfiddle/5y9bqwd0 – Felix Kling Commented Oct 22, 2017 at 3:05
  • And here is another option for child arrow function property: jsfiddle/zoeh5bp2. Bot of them are about closuring super from constructor. – dhilt Commented Oct 22, 2017 at 3:25
  • @FelixKling An earlier answer to this question referenced this bug report for Babel: github./babel/babel/issues/3930#issuement-245408381, explaining that the issue is linked to generators not being able to call super. – o01 Commented Oct 22, 2017 at 11:40
Add a ment  | 

2 Answers 2

Reset to default 6

The difference is that

sayName1 = () => {
    alert(this.name);
}

is a property with function type, while

sayName2() {
    alert(this.name);
}

is a method. And ES classes handle methods and properties in entirely different ways. Methods are existed on class prototype, while properties are being assigned to every instance. And you can't access parent's sayName1 via super.sayName1 due to it is not on your parent's class, it is only on instance object and could be accessed via instance.sayName1.

Also, from ECMAScript® 2015 Language Specification:

An ArrowFunction does not define local bindings for arguments, super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment... An ArrowFunction that references super is always contained within a non-ArrowFunction and the necessary state to implement super is accessible via the scope that is captured by the function object of the ArrowFunction.

As far as I understand, arrow functions act just like regular functions in most instances. However, when you are dealing with instances where the "this" keyword would e into play, the arrow function binds "this" to the context where it was defined. If you use a regular function you should have no problems.

发布评论

评论列表(0)

  1. 暂无评论