Khai báo nhiều biến trong JavaScript


333

Trong JavaScript, có thể khai báo nhiều biến như thế này:

var variable1 = "Hello World!";
var variable2 = "Testing...";
var variable3 = 42;

... Hoặc như thế này:

var variable1 = "Hello World!",
    variable2 = "Testing...",
    variable3 = 42;

Là một phương pháp tốt hơn / nhanh hơn phương pháp khác?


6
Để nhanh hơn , sử dụng jsperf này, tôi không thể thấy mức tăng tốc độ nhất quán bằng cách sử dụng phương pháp này hay phương pháp khác.
Majid fouadpour

Câu trả lời:


344

Cách đầu tiên là dễ dàng hơn để duy trì. Mỗi khai báo là một câu lệnh trên một dòng duy nhất, vì vậy bạn có thể dễ dàng thêm, xóa và sắp xếp lại các khai báo.

Với cách thứ hai, thật khó chịu khi xóa khai báo đầu tiên hoặc cuối cùng vì chúng chứa vartừ khóa và dấu chấm phẩy. Và mỗi khi bạn thêm một khai báo mới, bạn phải thay đổi dấu chấm phẩy trong dòng cũ thành dấu phẩy.


67
Nếu bạn đang viết mã mà bạn muốn thu nhỏ hoặc đóng gói sau, cách thứ hai cho phép máy nén (như Máy nén YUI) cung cấp cho bạn phiên bản rút gọn hơn. Nếu kích thước là một sự cân nhắc, thì tôi sẽ đề xuất làm theo càng nhiều đề xuất của JSLint càng tốt.
Ngõ

36
Jslint tuyên bố rằng cách thứ hai là chính đáng hơn nhưng tôi không đồng ý.
ThatGuy

29
Cách thứ hai là tối ưu hóa vi mô. Tất cả các khai báo var được xử lý cùng một lúc, thay vì một lần. Điều này không quan trọng lắm trong các trình duyệt hiện đại / máy tính hiện đại.
webnesto

18
@ 0xc0de: Tôi muốn xem bằng chứng khai báo tất cả các biến trong một câu lệnh là "hiệu quả". Nếu bạn chỉ đo lường hiệu quả như là một vài byte được lưu, thì có thể. Nhưng nếu bạn tính đến khả năng đọc và khả năng bảo trì, tôi nghĩ bạn sẽ thấy rằng tối ưu hóa sớm thường là cách sai, đặc biệt là vì các trình duyệt hiện đại sẽ thu thập và khởi tạo tất cả các biến trong phạm vi trên thẻ thực hiện trước. Cá nhân, tôi thấy có tất cả các biến được khai báo trong một dòng hoặc câu lệnh để làm cho việc hiểu mã nhanh hơn và dễ bị lỗi hơn.
ogradyjd

9
Liên quan đến hiệu quả, cả uglifyjs và trình biên dịch đóng google sẽ tự động gộp các câu lệnh var tuần tự thành một, kết xuất điểm đó (theo như tôi có thể nói YUI sẽ không làm điều này, tuy nhiên tôi chưa thử nghiệm rộng rãi).
bhuber

215

Bên cạnh khả năng bảo trì, cách đầu tiên giúp loại bỏ khả năng tạo ra các biến toàn cầu tai nạn:

(function () {
var variable1 = "Hello World!" // semicolon is missed out accidently
var variable2 = "Testing..."; // still a local variable
var variable3 = 42;
}());

Trong khi cách thứ hai ít tha thứ hơn:

(function () {
var variable1 = "Hello World!" // comma is missed out accidently
    variable2 = "Testing...", // becomes a global variable
    variable3 = 42; // a global variable as well
}());

4
Điểm tốt. Nếu chúng ngắn, thì viết trên một dòng sẽ tránh được vấn đề này : var variable1 = "Hello World!", variable2 = "Testing...", variable3 = 42;. Một người mất tích ,sẽ sụp đổ, nhưng tôi đồng ý rằng đó là rủi ro
Aram Kocharyan

14
Nếu bạn đang sử dụng chế độ nghiêm ngặt, bạn sẽ không thể tạo toàn cầu như thế này.
Danyal Aytekin

1
Tôi là một fan hâm mộ của việc khai báo nhiều biến trên một dòng bởi vì tôi nghĩ rằng nó trông sạch hơn. Điều đó nói rằng, vô tình khai báo các biến toàn cầu là một mối nguy hiểm thực sự. Trong khi tìm kiếm các rò rỉ bộ nhớ, tôi đã gặp nhiều trường hợp trong đó tôi vô tình khai báo một số biến toàn cục cùng một lúc vì tôi đã sử dụng dấu chấm phẩy thay vì dấu phẩy.
smabbott

+1 chỉ dành một nửa ngày và thậm chí bắt đầu tự hỏi tại sao có sự khác biệt không có giấy tờ giữa hai tuyên bố này. Sau đó đọc câu trả lời này, kiểm tra mã siêu cẩn thận và tìm thấy lỗi. Cần một kỳ nghỉ ...
Giedrius

1
Trình soạn thảo văn bản của tôi cung cấp cho tôi Possible Fatal Errornếu tôi hôn mê, vội vàng cho tôi!

33

Nó là phổ biến để sử dụng mộtvar tuyên bố cho mỗi phạm vi cho tổ chức. Cách tất cả các "phạm vi" theo một mô hình tương tự làm cho mã dễ đọc hơn. Ngoài ra, động cơ "nâng" tất cả chúng lên đầu dù thế nào đi nữa. Vì vậy, giữ cho các tuyên bố của bạn cùng bắt chước những gì thực sự sẽ xảy ra chặt chẽ hơn.


6
Bạn có thể giữ các khai báo cùng nhau mà không khiến chúng chia sẻ cùng một khai báo 'var'. Tôi hiểu và chấp nhận các giải thích được đưa ra tại jslint (liên kết của bạn) nhưng tôi không chia sẻ kết luận. Như đã nói ở trên, đó là vấn đề phong cách hơn bất cứ điều gì khác. Trong thế giới Java (trong số những người khác), khuyến nghị ngược lại (một khai báo trên mỗi dòng) để dễ đọc.
PhiLho

Dễ đọc hơn? Lý do duy nhất mà mọi người đặt chúng trên một dòng là lý do cụ thể của JS mà bạn đã đề cập: JS di chuyển tất cả các khai báo lên đầu. Nếu nó không làm điều đó, tất cả chúng ta sẽ tuyên bố các lọ của chúng ta gần nhất với điểm mà chúng được sử dụng.
Danyal Aytekin

@ vol7ron không phải là trường hợp đó, và là một sự hiểu lầm thô thiển về vartuyên bố. hoàn toàn ngược lại là đúng. xem tài liệuví dụ này
jackweirdy

@jackweirdy bạn đúng và đó là trường hợp, thực hiện kém hoặc lỗi trong các trình duyệt cũ hơn. Kể từ khi tôi xóa bình luận của tôi.
vol7ron

29

Nó dễ đọc hơn nhiều khi làm theo cách này:

var hey = 23;
var hi = 3;
var howdy 4;

Nhưng mất ít không gian và dòng mã theo cách này:

var hey=23,hi=3,howdy=4;

Nó có thể lý tưởng để tiết kiệm không gian, nhưng hãy để máy nén JavaScript xử lý nó cho bạn.


15

Có lẽ như thế này

var variable1 = "hello world"
, variable2 = 2
, variable3 = "how are you doing"
, variable4 = 42;

Ngoại trừ khi thay đổi biến đầu tiên hoặc biến cuối, nó rất dễ duy trì và đọc.


6
Thông thường, sử dụng dấu phẩy trước tiên, dấu chấm phẩy đi trên một dòng mới để ngăn chặn vấn đề đó. var biến1 = "hello world" \ n, biến2 = 2 \ n,
biến3

2
Đây là cú pháp Haskell. Tôi cảm thấy rằng bằng cách nào đó, nó không được khuyến khích / thực hành phổ biến trong javascript
shamanSK

14

Đó chỉ là vấn đề sở thích cá nhân. Không có sự khác biệt giữa hai cách này, ngoài một vài byte được lưu với dạng thứ hai nếu bạn loại bỏ khoảng trắng.


Cái thứ hai lưu một vài byte.
Sophie Alpert

Ben Alpert: Bạn thấy thế nào?
Josh Stodola

Nếu bạn loại bỏ khoảng trắng, hơn 'var foo = "hello", bar = "world";' khai báo chiếm ít ký tự hơn 'var foo = "hello"; var bar = "world";' Nếu bạn có một trang web phổ biến, việc lưu một vài byte trên JS có thể giúp ích (bạn cũng muốn giảm thiểu tên biến, v.v.)
Brian Campbell

Tôi thấy điều này các byte được lưu là không liên quan tại thời điểm này, do sự gia tăng của các công cụ khai thác JavaScript, đáng chú ý là chế độ đơn giản của Google Closer Compiler (cái gọi là).
Bryan Field

1
@webnesto không bao giờ có bất kỳ hiệu suất nào từ cú pháp khi ngữ nghĩa của cú pháp là như nhau. Người ta sẽ không thực thi mã ngay lập tức nhưng trước tiên phân tích nó và thực hiện phân tích ngữ nghĩa - đây là nơi cả hai kiểu khai báo được cân bằng.
Esailija

14

ECMAScript6 đã giới thiệu bài tập hủy diệt hoạt động khá hay:

[a, b] = [1, 2] asẽ bằng 1bsẽ bằng 2.


nó không trả lời câu hỏi, nhưng nó có thể là sự thay thế tốt hơn cho cả hai phương pháp được mô tả.
svarog

1
Tôi nghĩ rằng cách tiếp cận của bạn không thực sự khả thi trong trường hợp nếu bạn có danh sách dài các biến. Thật khó để nói biến nào có giá trị nào liên quan và bạn cũng không được bảo vệ khỏi các lỗi là trường hợp hợp nhất xấu trong đó bạn vô tình có thể xóa một phần tử khỏi một mảng. Ví dụ: let [aVar, bVar, cVar, xVar, yVar, zVar] = [10, 20, 30, 40, 50]; Vì vậy, cá nhân tôi không khuyên bạn nên nó.
Kirill Reznikov

1
tiện dụng nếu bạn muốn đặt nhiều biến có cùng giá trị. Ví dụ, sử dụng để đặt lại về 0 trong một vòng lặp.
Nick

Đúng! đây là những gì tôi đang tìm kiếm Đặc biệt nếu bạn muốn xác định một cặp hai chiều, hoặc các giá trị đa chiều, nhưng không phải là mảng.
Eugene Kardash

11
var variable1 = "Hello World!";
var variable2 = "Testing...";
var variable3 = 42;

dễ đọc hơn:

var variable1 = "Hello World!",
    variable2 = "Testing...",
    variable3 = 42;

Nhưng họ làm điều tương tự.


Sử dụng ít "không gian tập tin"? Tôi nghĩ rằng bạn có một số giải thích để làm.
Josh Stodola

@JoshStodola trông giống như không gian tệp với tôi. Kể từ đó, thay var<space>vào đó<space><space><space><space>
CÔNG TRÌNH

@WORMSS trừ khi đó là var<space>hay var<tab>vs <tab>. Vẫn chủ yếu là moot.
mpag

9

Sử dụng ES6 phân Destructuring : Nó sẽ giải nén các giá trị từ mảng, hoặc tài sản từ các đối tượng, vào biến rõ rệt.

let [variable1 , variable2, variable3] = 
["Hello World!", "Testing...", 42];

console.log(variable1); // Hello World!
console.log(variable2); // Testing...
console.log(variable3); // 42


4
Đó là một ý tưởng khủng khiếp, đặc biệt nếu bạn cần chỉ định khoảng 10 biến.
Kirill Reznikov

7

Việc sử dụng duy nhất nhưng cần thiết cho dấu phẩy của tôi là trong một vòng lặp for:

for (var i = 0, n = a.length; i < n; i++) {
  var e = a[i];
  console.log(e);
}

Tôi đã đến đây để tìm kiếm xem điều này có ổn trong JavaScript không.

Ngay cả khi nhìn thấy nó hoạt động, một câu hỏi vẫn còn cho dù n là cục bộ của hàm.

Điều này xác minh, n là cục bộ:

a=[3,5,7,11];
(function l () { for (var i = 0, n = a.length; i < n; i++) {
  var e = a[i];
  console.log(e);
}}) ();
console.log(typeof n == "undefined" ?
  "as expected, n was local" : "oops, n was global");

Trong một khoảnh khắc tôi không chắc chắn, chuyển đổi giữa các ngôn ngữ.


7

Mặc dù cả hai đều hợp lệ, việc sử dụng lần thứ hai không khuyến khích các nhà phát triển thiếu kinh nghiệm đặt các câu lệnh var ở khắp mọi nơi và gây ra các vấn đề nâng hàng. Nếu chỉ có một var cho mỗi hàm, ở đầu hàm, thì việc gỡ lỗi mã sẽ dễ dàng hơn. Điều này có thể có nghĩa là các dòng nơi các biến được khai báo không rõ ràng như một số có thể thích.

Tôi cảm thấy rằng sự đánh đổi là xứng đáng, nếu điều đó đồng nghĩa với việc loại bỏ một nhà phát triển khỏi việc bỏ 'var' bất cứ nơi nào họ cảm thấy thích.

Mọi người có thể phàn nàn về JSLint, tôi cũng vậy, nhưng rất nhiều trong số đó không hướng đến việc khắc phục các vấn đề với ngôn ngữ, mà là sửa chữa các thói quen xấu của các lập trình viên và do đó ngăn chặn các vấn đề trong mã họ viết. Vì thế:

"Trong các ngôn ngữ có phạm vi khối, người ta thường khuyến nghị các biến được khai báo tại trang sử dụng đầu tiên. Nhưng vì JavaScript không có phạm vi khối, nên khôn ngoan hơn khi khai báo tất cả các biến của hàm ở đầu hàm. Đó là khuyến nghị rằng một câu lệnh var được sử dụng cho mỗi hàm. " - http://www.jslint.com/lint.html#scope


6

Tôi nghĩ đó là vấn đề sở thích cá nhân. Tôi thích làm theo cách sau:

   var /* Vars */
            me = this, that = scope,
            temp, tempUri, tempUrl,
            videoId = getQueryString()["id"],
            host = location.protocol + '//' + location.host,
            baseUrl = "localhost",
            str = "Visit W3Schools",
            n = str.search(/w3schools/i),
            x = 5,
            y = 6,
            z = x + y
   /* End Vars */;

6

Một lý do khác để tránh phiên bản câu lệnh đơn ( var ) là gỡ lỗi. Nếu một ngoại lệ được ném trong bất kỳ dòng gán nào, dấu vết ngăn xếp chỉ hiển thị một dòng.

Nếu bạn có 10 biến được xác định bằng cú pháp dấu phẩy, bạn không có cách nào để biết trực tiếp biến nào là thủ phạm.

Phiên bản tuyên bố cá nhân không bị sự mơ hồ này.


2

Khái niệm "Sự gắn kết trên khớp nối" có thể được áp dụng chung hơn là chỉ các đối tượng / mô-đun / chức năng. Nó cũng có thể phục vụ trong tình huống này:

Ví dụ thứ hai mà OP đề xuất đã ghép tất cả các biến vào cùng một câu lệnh, điều này khiến cho không thể lấy một trong các dòng và di chuyển nó đến một nơi khác mà không phá vỡ công cụ (khớp nối cao). Ví dụ đầu tiên ông đưa ra làm cho các phép gán biến độc lập với nhau (khớp nối thấp).

"Khớp nối thấp thường là dấu hiệu của một hệ thống máy tính có cấu trúc tốt và thiết kế tốt, và khi kết hợp với sự gắn kết cao, sẽ hỗ trợ các mục tiêu chung về khả năng đọc và bảo trì cao."

http://en.wikipedia.org/wiki/Coupling_(computer_programming)

Vì vậy, chọn cái đầu tiên.


1
Tôi không thấy làm thế nào điều này có liên quan đến khớp nối hoặc sự gắn kết. Quan tâm đến công phu?
Edson Medina

Ví dụ thứ hai mà OP đề xuất đã ghép tất cả các biến vào cùng một câu lệnh, điều này khiến cho không thể lấy một trong các dòng và di chuyển nó đến một nơi khác mà không phá vỡ công cụ (khớp nối cao). Ví dụ đầu tiên ông đưa ra làm cho các phép gán biến độc lập với nhau (khớp nối thấp).
Magne

Khớp nối là về sự phụ thuộc lẫn nhau giữa các mô-đun / đối tượng / chức năng khác nhau, KHÔNG phải là dòng mã!
Edson Medina

1
Ban đầu nó là về các mô-đun, vâng, nhưng khái niệm này có thể được áp dụng chung hơn, vì ngay cả việc đưa các đối tượng / hàm của bạn vào định nghĩa cho thấy.
Magne

2

Một bài viết cũ, tôi biết, nhưng để thêm một chi tiết nhỏ về phối cảnh cho các nhân viên Google:

Vấn đề bảo trì có thể được khắc phục khá dễ dàng với một chút định dạng, như vậy.

let
  my_var1 = 'foo',
  my_var2 = 'bar',
  my_var3 = 'baz'
;

Tôi sử dụng định dạng này một cách nghiêm ngặt như một vấn đề sở thích cá nhân. Tôi bỏ qua định dạng này cho các khai báo đơn, tất nhiên, hoặc nơi nó chỉ đơn giản là tổng hợp các tác phẩm.


1

Tôi tin rằng trước khi chúng tôi bắt đầu sử dụng ES6, cách tiếp cận với khai báo var duy nhất không tốt cũng không xấu (trong trường hợp nếu bạn có linters và 'use strict'. Đó thực sự là sở thích của tôi. Nhưng bây giờ mọi thứ đã thay đổi đối với tôi. :

  1. Bây giờ chúng ta có hai loại biến mới và vartrở nên lỗi thời. Đó là thực hành tốt để sử dụng constở mọi nơi cho đến khi bạn thực sự cần let. Vì vậy, khá thường xuyên, mã của bạn sẽ chứa các khai báo biến với phân tích ở giữa mã và do phạm vi khối, bạn sẽ thường xuyên di chuyển các biến giữa các khối trong trường hợp có thay đổi nhỏ. Tôi nghĩ rằng sẽ thuận tiện hơn khi làm điều đó với các tuyên bố đa dòng.

  2. Cú pháp ES6 trở nên đa dạng hơn, chúng tôi có các hàm hủy, chuỗi mẫu, hàm mũi tên và các xác nhận tùy chọn. Khi bạn sử dụng nhiều tất cả các tính năng đó với các khai báo var đơn, điều đó làm tổn thương khả năng đọc.


0

Tôi nghĩ rằng cách đầu tiên (nhiều vars) là tốt nhất, vì nếu không bạn có thể kết thúc bằng cách này (từ một ứng dụng sử dụng Knockout), rất khó đọc theo ý kiến ​​của tôi:

    var categories = ko.observableArray(),
        keywordFilter = ko.observableArray(),
        omniFilter = ko.observable('').extend({ throttle: 300 }),
        filteredCategories = ko.computed(function () {
            var underlyingArray = categories();
            return ko.utils.arrayFilter(underlyingArray, function (n) {
                return n.FilteredSportCount() > 0;
            });
        }),
        favoriteSports = ko.computed(function () {
            var sports = ko.observableArray();
            ko.utils.arrayForEach(categories(), function (c) {
                ko.utils.arrayForEach(c.Sports(), function (a) {
                    if (a.IsFavorite()) {
                        sports.push(a);
                    }
                });
            });
            return sports;
        }),
        toggleFavorite = function (sport, userId) {
            var isFavorite = sport.IsFavorite();

            var url = setfavouritesurl;

            var data = {
                userId: userId,
                sportId: sport.Id(),
                isFavourite: !isFavorite
            };

            var callback = function () {
                sport.IsFavorite(!isFavorite);
            };

            jQuery.support.cors = true;
            jQuery.ajax({
                url: url,
                type: "GET",
                data: data,
                success: callback
            });
        },
        hasfavoriteSports = ko.computed(function () {
            var result = false;
            ko.utils.arrayForEach(categories(), function (c) {
                ko.utils.arrayForEach(c.Sports(), function (a) {
                    if (a.IsFavorite()) {
                        result = true;
                    }
                });
            });
            return result;
        });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.