在Javascript中,类和函数的行为有何不同?

时间:2018-04-06 00:28:36

标签: javascript ecmascript-6

我的理解是所有类本质上都是函数,所有实例本质上都是对象。但有些事让我感到困惑。



//Take this for example:

    function AnimalFunc(name) {
        this.name = name;
        this.sayName = function() {
            console.log(this.name);
        }
    }

//And compare it with this:

    class AnimalClass {
        constructor(name) {
            this.name = name;
        }
        
        sayName() {
            console.log(this.name);
        }
    }

//Now I instantiate them.

    cat = new AnimalFunc("cat")
    cat.sayName() // -> "cat"
    dog = new AnimalClass("dog")
    dog.sayName() // -> "dog"
    
    console.log(Object.keys(cat));
    console.log(Object.keys(dog));




预期观察结果:

  1. typeof(AnimalClass)typeof(AnimalFunc)都返回function
  2. typeof(cat)typeof(dog)都返回object
  3. 意外观察:

    1. 如果我Object.keys(cat),我会["name","sayname"]
    2. 但如果我Object.keys(dog),我会["name"]
    3. 我的问题是:为什么我不将sayname作为类实例的键?为什么我只为函数实例获取它?

3 个答案:

答案 0 :(得分:4)

第一个带有函数的示例在创建实例时创建一个新的函数属性,因此,Object.keys可以获取一个新的键。

第二个示例,带有一个类,将函数属性赋给对象prototype。因此,实际上并未创建新密钥,并且可以通过走原型链找到sayName函数。

您可以通过执行以下操作来复制类行为:

function AnimalFunc(name) {
  this.name = name
}

AnimalFunc.prototype.sayName = function () {
  console.log(this.name)
}

Here's some reading if you want to familiarize yourself with JS's prototype model.如果您愿意,可以通过搜索" javascript原型"来查找更多文章等。

答案 1 :(得分:3)

因为您已声明了两个名为saynamethis.name; this.sayname;

的属性
AnimalClass

在类name中,您只将构造函数体中的键this.name = .... 声明为属性:

this
  

Object.keys()返回一个数组,其元素是与直接在对象上找到的可枚举属性相对应的字符串。属性的顺序与通过手动循环对象的属性给出的顺序相同。

因此,基本上将返回使用上下文class AnimalClass { constructor(name) { this.name = name; // This is just to illustrate! this.sayName = function() { console.log(this.name); } } } console.log(Object.keys(new AnimalClass('Dog')))直接声明的属性。

的示例
  • 构造函数体内的函数声明



{{1}}




答案 2 :(得分:1)

这是因为 AnimalClass &#39; s sayName位于 AnimalClass 的原型中,而 AnimalFunc < / strong>&#39; s this不是,它是实例的一部分(sayName)。

对于 AnimalClass ,只有一个class AnimalClass { constructor(name) { this.name = name; } sayName() { console.log(this.name); } } var a = new AnimalClass("a"), b = new AnimalClass("b"); a.sayName === b.sayName; // true函数,所有实例共享对以下内容的引用:

&#13;
&#13;
sayName
&#13;
&#13;
&#13;

每个 AnimalFunc 实例都有自己的function AnimalFunc(name) { this.name = name; this.sayname = function() { console.log(this.name); } } var a = new AnimalFunc("a"), b = new AnimalFunc("b"); a.sayName === b.sayName; // false定义,因为它在构造函数中为每个实例重新定义:

&#13;
&#13;
function
&#13;
&#13;
&#13;

使用function AnimalFunc(name) { this.name = name; } AnimalFunc.prototype.sayname = function() { console.log(this.name); } AnimalClass 的等效是:

class

使用class AnimalClass { constructor(name) { this.name = name; this.sayName = function() { console.log(this.name); } } } AnimalFunc 相当于:

mix phoenix.server