在JavaScript和Java中继承时,为什么`this`表现不同?

时间:2018-05-27 14:26:11

标签: javascript java inheritance dynamic-languages

我怀疑this在继承时JavaScript和Java是不同的行为。

在java中:

class Animal {
    public String name = "animal";

    void hello() {
        System.out.println("hello " + this.name);
    }
}

class Dog extends Animal {
    public String name = "dog";
}

public class Main {
    public static void main(String...args) {
        Dog dog = new Dog();
        dog.hello(); // hello animal
    }
}

上面的代码将输出hello animal,似乎当我在子类Dog的实例中调用hello方法时,它将在父类Animal中输出name属性。

但它在Javascript中有所不同:

class Animal {
    constructor() {
        this.name = 'animal';
    }

    hello() {
        console.log('hello ' + this.name);
    }
}

class Dog extends Animal {
    constructor() {
        super();
        this.name = 'dog';
    }
}

const dog = new Dog();
dog.hello(); // hello dog

如您所见,具有相同逻辑输出的代码会产生不同的结果。在JavaScript代码中,hello方法输出hello dog,它是子类实例的名称属性。

我也尝试使用Python和C ++,结果是Python的行为与JavaScript类似,而C ++的行为与Java类似。

那是因为JavaScript和Python是动态语言吗?但是有什么细节以及为什么它们被设计成这个?

我应该读哪本书来了解它?

非常感谢,原谅英语不好......

2 个答案:

答案 0 :(得分:1)

MDN是一个开始。

针对程序员的大多数Javascript书籍都将涵盖“这个”。

Learning Javascript部分中有一系列图书。网上有几本免费书籍。

答案 1 :(得分:1)

在C ++和Java中,只有函数可以是虚拟的(即动态查找)。而在Python和JavaScript中,动态查找所有属性/属性/字段。据推测,C ++和Java不希望语言承诺超过可以用零开销或低开销实现。而Python和JavaScript不太关心开销,而更关心的是使语言能够满足您的需求。

如果您希望C ++的行为与JavaScript类似,那么您必须编写一个虚拟访问器函数来访问相应的字段。

class Animal {
  string name_;

  public:
    Animal() : name_ {"animal"} {
    }

    virtual string name() const {
      return name_;
    }

    void hello() {
        cout << "hello " << name();
    }
};

class Dog : public Animal {
  string name_;

  public:
    Dog() : name_ {"dog"} {
    }

    string name() const override {
      return name_;
    }
};

int main() {
  Dog dog;
  dog.hello(); // hello dog
}