簡體   English   中英

定義函數的最佳方法是什么?

[英]Best way to define a function?

我總是學會在JavaScript中定義一個函數,如下所示:

function myFunction(arg1, arg2) { ... }

但是,我剛剛閱讀了谷歌的Javascript指南 ,它提到我應該定義這樣的方法:

Foo.prototype.bar = function() { ... };

問題 :示例中的“Foo”是Object,還是名稱空間? 為什么Google示例不是以下代碼(不起作用):

prototype.bar = function() { ... };

更新 :如果它有助於了解,我的所有JavaScript都將由用戶瀏覽器調用我的Web應用程序。

你的兩個例子在功能上並不相同。 第一個示例只是定義一個函數(可能是全局函數,除非您在另一個函數中定義它)。 第二個例子擴展了構造函數的原型。 可以把它想象為向Foo類添加方法。

除非您正在構建JavaScript庫,否則我的建議是既不使用也不使用某種命名空間系統。 創建一個充當命名空間的全局對象,通過該命名空間可以訪問所有功能。

var MyObject = {
    utils: {
        someUtil: function() {},
        anotherUtil: function() {}
    },
    animation: {
        // A function that animates something?
        animate: function(element) {}
    }
};

然后:

// Assuming jQuery, but insert whatever library here
$('.someClass').click(function() {
    MyObject.animation.animate(this);
});

如果要在JavaScript中模擬類,可以將“類”定義為函數(函數本身是構造函數),然后通過prototype屬性添加方法。

function Foo() {
    // This is the constructor--initialize any properties
    this.a = 5;
}
// Add methods to the newly defined "class"
Foo.prototype = {
    doSomething: function() { /*...*/ },
    doSomethingElse: function() { /*...*/ }
};

然后:

var bar = new Foo();
console.log(bar.a); // 5
bar.doSomething();
// etc...

我總是學會在JavaScript中定義一個函數,如下所示: function myFunction(arg1, arg2) { ... }

有兩種方法可以定義函數。 作為函數聲明

function foo(...) {
    ...
}

或者作為函數表達式

var foo = function() {
    ...
};

在這里 閱讀 更多

但是,我剛剛閱讀了谷歌的Javascript指南,它提到我應該定義這樣的方法: Foo.prototype.bar = function() { ... };

這特別與對象的方法創建有關,而不僅僅是普通的獨立函數。 假設您有基礎對象聲明:

var Foo = function() {
    ...
};

與任何其他賦值一樣,要將函數賦值給對象的屬性,必須使用賦值表達式。 你可以用兩種方法做到這一點。 簡潔而通用的方式(根據Google的參考建議)

Foo.prototype.bar = function() {};

或者,如果您想繼續使用定義函數的聲明形式

function bar() {
    ...
};
Foo.prototype.bar = bar;

這通常比必要的更冗長,但在您希望將相同方法分配給多個對象原型的情況下可能很有用。

問題:示例中的“Foo”是Object,還是名稱空間? 為什么Google示例中沒有以下代碼(不起作用): prototype.bar = function() { ... };

  1. Foo是一個對象。 盡管這個概念可以通過靜態對象的使用來表達,正如我在回答你的另一個問題時所表明的那樣,JavaScript中沒有名稱空間。 此外,特別是在給出的示例代碼中, Foo可能旨在成為實例化對象,這使其無法像命名空間那樣運行。

  2. 當然它不起作用: prototype尚未定義為對象(當然,除非您將其定義為對象)。 prototype 屬性存在於每個對象上(函數也是一個對象),這就是為什么你可以做Foo.prototype.bar = ...; 在這里 閱讀 更多

=====> 2017年更新<=====

這個問題和答案是7歲 ,非常過時。 此答案包括ES5ES6版本的新語法,並與ES7兼容。


定義函數的最佳方法是什么?

沒有一種“最佳”方式來定義函數。 如何定義函數取決於函數的預期用途和生命周期。

全球職能

定義為帶有函數標記的語句,后跟帶有小寫camelcase的函數名稱

function functionName (arguments) {
    // function body
}

優於函數表達式...

var functionName = function (arguments) {
     // function body
}

...因為在執行定義行之前不會發生對函數變量的賦值。 與在執行任何代碼之前解析后立即可用的首選方法不同。

const functionName = function(arguments){/*function body*/}
var functionName = function functionName(arguments){/*function body*/}
var functionName = function functionAltName(arguments){/*function body*/}

功能對象

作為帶有大寫camelcase函數名的函數語句

function MyObjectFunction (arguments) {
    /*function body*/
    // if this function is called with the new token
    // then it exits with the equivalent return this;
}

const obj = new MyObjectFunction(foo);

匿名函數表達式。

一種常見的做法是通過一個沒有名稱的立即調用的函數來創建對象(因此是匿名的)

;(function (arguments) { /*function body*/ } ("argument val"))

要么

;(function(arguments){ /*function body*/ })("argument val")

注意包含; 這個功能。 這非常重要,因為打開“(”將阻止在函數上方的任何代碼上插入自動分號。

立即調用函數表達式。

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
}());

const functionResult = (function (arguments) {
      /*function body*/
      return functionResult;
})();

作為var或塊范圍的constlet

匿名回調。

使用ES6,您應該使用箭頭函數語法而不是匿名函數表達式。

 myArray.forEach((item,i) => {/*function body*/});
 myArray.filter(item => !item);
 setTimeout(() => {/*function body*/}, 1000);

作為屬性的功能。

使用對象聲明函數的簡寫語法。

var myObj = {
    functionName (arguments) {/*function body*/},
}

// called 
myObj.functionName("arg");

比...好

var myObj = {
    functionName : function (arguments) {/*function body*/},
}

或者通過函數對象聲明

function MyObjectFunction(arguments){
     this.propertyFunction = function(arguments) { /*function body*/ }
     // or arrow notation is fine
     this.propertyFunction = (argument) => { /*function body*/ };
}

作為原型的功能

function MyObj (arguments) {
      MyObj.prototype.functionName = function(arguments) { /*function body*/ }
}

要么

function MyObj (arguments) {}
MyObj.prototype.functionName = function(arguments) { /*function body*/ }

要么

MyObj.prototype = {
    functionName(arguments) { /*function body*/ }
}

在JavaScript中創建構造函數或“類”時,定義原型函數很有用。 例如,你將是new

var MyClass = function(){};
MyClass.prototype.doFoo = function(arg){ bar(arg); }

但在普通的舊圖書館功能中沒有用處,例如

function doPopup(message){ /* create popup */};

使用原型功能有幾個好處,包括但不限於

  • 速度
  • 內存使用情況
  • 可擴展性

但是,同樣,這是在為可實例化的“類”創建構造函數的上下文中

HTH

它的工作原理如下:

(function(){ // create an isolated scope
    // My Object we created directly
    var myObject = {
        a: function(x,y) {
            console.log('a');
        },
        b: function(x,y) {
            console.log('b');
            this.a(x,y);
        }
    };
})();

(function(){ // create an isolated scope

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Define a function that should never inherit
    myClass.c = function(x,y) {
        console.log('myClass: c');
        this.a(x,y);
    };

    // Create Object from Class
    var myObject = new myClass();
    // Will output:
    // myClass: constructor
    // myClass: b
    // myClass: a

    // Define a function that should never inherit
    myObject.d = function(x,y) {
        console.log('myObject: d');
        this.a(x,y);
    };

    // Test the world is roung
    console.log(typeof myClass.c, 'should be undefined...');
    console.log(typeof myClass.d, 'should be function...');
})();

(function(){ // create an isolated scope
    // If you are using a framework like jQuery, you can obtain inheritance like so

    // Create a Object by using a Class + Constructor
    var myClass = function(x,y) {
        console.log('myClass: constructor');
        this.b(x,y);
    };
    myClass.prototype = {
        a: function(x,y) {
            console.log('myClass: a');
        },
        b: function(x,y) {
            console.log('myClass: b');
            this.a(x,y);
        }
    };

    // Create new Class that inherits
    var myOtherClass = function(x,y) {
        console.log('myOtherClass: constructor');
        this.b(x,y);
    };
    $.extend(myOtherClass.prototype, myClass.prototype, {
        b: function(x,y) {
            console.log('myOtherClass: b');
            this.a(x,y);
        }
    });

    // Create Object from Class
    var myOtherObject = new myOtherClass();
    // Will output:
    // myOtherClass: constructor
    // myOtherClass: b
    // myClass: a
})();

(function(){ // create an isolated scope
    // Prototypes are useful for extending existing classes for the future
    // Such that you can add methods and variables to say the String class
    // To obtain more functionality
    String.prototype.alert = function(){
        alert(this);
    };
    "Hello, this will be alerted.".alert();
    // Will alert:
    // Hello, this will be alerted.
})();

編輯:修復代碼,以便在您復制並粘貼時它將實際在您的瀏覽器中運行:-)

Foo既是Object又是命名空間。 看到這個問題

使用對象作為名稱空間可防止名稱沖突。 這總是一個好主意,但尤其是在您開發和/或使用共享庫時。

如果您不希望制作多個Foo對象(因此不需要面向對象的樣式),您可以在單個對象上創建函數作為方法:

var Foo = {}
Foo.bar = function() { ... }

要么

var Foo = {
    bar: function() {...},
    quux: function() {...}
};

然后,您只需將該函數調用為:

Foo.bar()

(這種聲明大致相當於C ++或Java中的靜態方法。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM