2016-08-29 30 views
3

我有3個對象這樣的:如何在JavaScript中對類,函數和函數屬性進行分類?

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 
    } 
}; 

你可以seePerson是一類,AddMath.multiply的功能。

我的問題:在這種情況下如何分類classfunctions

我的問題來自:Person看起來像一個函數,就像這樣:

let Person = function (name, age) { 
    this._name = name; 
    this._age = age; 
}; 

而且,不存在任何問題,如果我聲明瞭一個對象來獲取Add功能的新實例:

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

new operator說:

新操作員創建一個in立場的一個用戶定義的對象類型或 內置對象類型之一,具有構造函數。

所有的3例,PersonAddMath.multiply是構造函數。所以:

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

然後,因爲所有的人都構造,它是如此難以歸類classfunction(對我來說)。

有沒有辦法做到這一點?

+3

對不起,你最終的目標是什麼?以「分類和功能」......在某種意義上說?爲了什麼目的,你需要這種分類?分類會改變你的代碼的工作方式嗎? –

+0

@JaromandaX在我的例子中。 'class'看起來像一個'function',而'function'看起來像'class'。我想分類它。 'Person'是一個類,'Add'和'Math.multiply'是函數。 –

+0

那裏,你剛剛歸類他們 –

回答

8

我認爲你的問題源於很容易理解的混淆:儘管有class語法,JavaScript並沒有像某些基於類的OOP語言(Java,C#,C++)那樣的功能區別開來。 class語法創建一個函數和該函數的prototype屬性引用的對象上的相關屬性。這不是一個單獨的事情。請參閱下面的酒吧獲取更多信息

此外,JavaScript最初並沒有在普通函數和構造函數之間做任何區分;這完全取決於你如何使用它們(例如,通過new或直接調用它們)。在ES2015中引入了語法和箭頭函數,語言正朝着區分不同類型的函數(如果您在不使用new的情況下調用它們,將會引發錯誤;如果您使用做了,箭頭函數將引發錯誤通過new致電)。

如果你的目標是看Person代碼,知道它是否與classfunction創建,無需調用它,做到這一點的唯一方法是將其轉換爲字符串並查看結果。規格requiresFunction.prototype.toString返回一個字符串...

...必須有一個FunctionDeclarationFunctionExpressionGeneratorDeclarationGeneratorExpressionClassDeclarationClassExpressionArrowFunctionMethodDefinition,或GeneratorMethod取決於對象的實際特性的語法。

因此,舉例來說,如果我用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" 

// 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" 

重新class創建功能:這是從字面上它做什麼:

class Foo { 
 
} 
 
console.log(typeof Foo); // "function"

事實上,這樣的:

class Foo { 
} 

大致翻譯

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'"); 
    } 
}; 

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

大致翻譯

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 + "!"); 
    } 
}; 
+0

「JavaScript沒有與函數不同的類」---這需要一些細節。 – zerkms

+0

@zerkms:我立即用*語句創建了一個函數和關聯屬性,該函數引用了該函數的'prototype'屬性。「*這對我來說似乎是一個相當詳細的闡述。不過,我確實回去添加了一些例子。 –

+0

「類語法創建一個函數」---我的觀點更多,是否需要遵循標準? – zerkms