如何在javascript中对类,函数和函数属性进行分类?

Tân*_*Tân 3 javascript

我有3个这样的对象:

class Person {
    constructor(name, age) {
        this._name = name;
        this._age = age;
    }
}

let Add = function (a, b) {
    return a + b
};

let Math = {
    multiply: function (x, y) {
        return x * y
    }
};
Run Code Online (Sandbox Code Playgroud)

尽可能地see,Person是一个类,Add并且Math.multiply是函数.

我的问题:如何分类class,functions在这种情况下?

我的问题来自:Person看起来像一个函数,像这样:

let Person = function (name, age) {
    this._name = name;
    this._age = age;
};
Run Code Online (Sandbox Code Playgroud)

此外,如果我声明一个对象来获取新的Add函数实例,则没有问题:

let result = new Add(2, 3); // this is allowed although it just needn't
Run Code Online (Sandbox Code Playgroud)

新运营商说:

new运算符创建用户定义的对象类型的实例或具有构造函数的内置对象类型之一.

所有的3例,Person,AddMath.multiply是构造函数.所以:

let person = new Person('Hermione', 18); // allowed
let result = new Add(2, 3); // allowed
result = new Math.multiply(2, 2); // allowed
Run Code Online (Sandbox Code Playgroud)

然后,因为所有的人都构造,它是如此难以归类classfunction(对我来说).

有没有办法实现这一目标?

T.J*_*der 8

我认为你的问题源于可以理解的混淆:尽管存在class语法,但JavaScript并没有像某些基于类的OOP语言那样的函数(Java,C#,C++).class语法在该函数的属性引用的对象上创建函数和关联的prototype属性.这不是一个单独的事情.请参阅下面的栏目了解更多信息

此外,JavaScript最初没有区分正常函数和构造函数; 这完全取决于你如何使用它们(例如,通过new或直接调用它们).作为推出两个ES2015的class语法和箭头的功能,语言向区分不同类型的函数(创建通过那些移动class,如果你打电话给他们,而不将抛出一个错误new;如果箭头功能将抛出一个错误通过调用它们new).

如果你的目标是看Person代码,并知道它是否与创建classfunction不调用它,做到这一点的唯一方法是将其转换为字符串并查看结果.该规范要求Function.prototype.toString返回一个字符串,...

...必须具有FunctionDeclaration,FunctionExpression,GeneratorDeclaration,GeneratorExpression,ClassDeclaration,ClassExpression,ArrowFunction,MethodDefinitionGeneratorMethod的语法,具体取决于对象的实际特征.

因此,例如,如果我已经使用过class Foo { },那么Foo.toString()必须返回一个class声明或表达式,而如果我使用了function Foo { }它,它必须返回一个function声明或表达式.所以你可以用正则表达式来解决它.

在评论中你问过zerkms

但在javascript中我可以使用AddMath.multiply作为类.如果我可以像类一样使用函数,那会更好吗?不,不是.

它完全取决于如何定义AddX.multiply (我真的不会影响内置Math对象):通过调用它们可能是有意义的new.对象属性作为对构造函数的引用并不罕见:

let Nifty = {
    Stuff: class {
        constructor(name) {
            this.name = name;
        }
    }
};
let x = new Nifty.Stuff("Coolness");
console.log(x.name); // "Coolness"
Run Code Online (Sandbox Code Playgroud)

要么

// Better not to do this, but it's allowed
let Nifty = {
    Stuff: function(name) {
        this.name = name;
    }
};
let x = new Nifty.Stuff("Coolness");
console.log(x.name); // "Coolness"
Run Code Online (Sandbox Code Playgroud)

重新class创建功能:这就是它的功能:

class Foo {
}
console.log(typeof Foo); // "function"
Run Code Online (Sandbox Code Playgroud)

事实上,这个:

class Foo {
}
Run Code Online (Sandbox Code Playgroud)

粗略地翻译成

let Foo = function() {
    if (!(this instanceof Foo)) { // This check isn't quite right, but it's close
        throw new TypeError("Class constructor Foo cannot be invoked without 'new'");
    }
};
Run Code Online (Sandbox Code Playgroud)

class Foo {
    constructor(name) {
        this.name = name;
    }
    sayHello() {
        console.log(`Hi, my name is ${name}!`);
    }
}
Run Code Online (Sandbox Code Playgroud)

粗略地翻译成

let Foo = function(name) {
    if (!(this instanceof Foo)) { // This check isn't quite right, but it's close
        throw new TypeError("Class constructor Foo cannot be invoked without 'new'");
    }
    this.name = name;
};

Foo.prototype.sayHello = function sayHello() {
        console.log("Hi, my name is " + name + "!");
    }
};
Run Code Online (Sandbox Code Playgroud)

  • @zerkms:是的,它是:http://www.ecma-international.org/ecma-262/7.0/index.html#sec-runtime-semantics-classdefinitionevaluation (3认同)