Mục đích của từ khóa var là gì và khi nào tôi nên sử dụng nó (hoặc bỏ qua nó)?


1543

LƯU Ý : Câu hỏi này được hỏi từ quan điểm của ECMAScript phiên bản 3 hoặc 5. Các câu trả lời có thể trở nên lỗi thời khi giới thiệu các tính năng mới trong bản phát hành ECMAScript 6.

Chính xác thì chức năng của vartừ khóa trong JavaScript là gì và sự khác biệt giữa

var someNumber = 2;
var someFunction = function() { doSomething; }
var someObject = { }
var someObject.someProperty = 5;

someNumber = 2;
someFunction = function() { doSomething; }
someObject = { }
someObject.someProperty = 5;

?

Khi nào bạn sẽ sử dụng một trong hai, và tại sao / nó làm gì?


3
Khi xâu chuỗi các khai báo var, việc đặt một dòng mới sau dấu phẩy có ảnh hưởng đến hành vi không? var x = 1, y = 2, [trở lại] z = 3;
Alfabravo

4
Không sử dụng "var" cũng khiến bạn bị lộ trong trường hợp tên biến bạn chọn là biến toàn cục được xác định trước đó. Xem hành trình đau buồn của tôi ở đây: stackoverflow.com/questions/16704014/ mẹo
Scott C Wilson

5
Bài đăng trên blog meloncard của @Ray (chắc chắn đáng đọc) đã chuyển sang blog.safeshepherd.com/23/how-one-missing-var-ruined-our-launch
Hephaestus

Tôi chưa bao giờ tưởng tượng một bài thơ có thể truyền cảm hứng cho tôi xem xét cho một vấn đề lập trình
Félix Gagnon-Grenier

1
@Gibolt nhưng nhìn vào ngày câu hỏi, đó là một câu hỏi không công bằng khi triệu tập một câu hỏi năm 2009 để nói điều đó. Mặc dù, nó vẫn còn hiệu lực như ngày nay đối với khả năng bảo trì, có một loạt các mã không "hiện đại".
Andre Figueiredo

Câu trả lời:


1356

Nếu bạn ở trong phạm vi toàn cầu thì không có nhiều khác biệt. Đọc câu trả lời của Kangax để được giải thích

Nếu bạn đang ở trong một hàm thì varsẽ tạo một biến cục bộ, "no var" sẽ tra cứu chuỗi phạm vi cho đến khi nó tìm thấy biến hoặc chạm vào phạm vi toàn cầu (tại điểm đó nó sẽ tạo ra nó):

// These are both globals
var foo = 1;
bar = 2;

function()
{
    var foo = 1; // Local
    bar = 2;     // Global

    // Execute an anonymous function
    (function()
    {
        var wibble = 1; // Local
        foo = 2; // Inherits from scope above (creating a closure)
        moo = 3; // Global
    }())
}

Nếu bạn không làm bài tập thì bạn cần sử dụng var:

var x; // Declare x

31
Là "không thực sự khác biệt nhiều" == "Không khác biệt"?
Alex

65
Vâng, thực sự là có, có sự khác biệt :) Cho dù sự khác biệt đó là quan trọng là một câu hỏi khác. Xem câu trả lời của tôi xuống thêm: stackoverflow.com/questions/1470488/ từ
kangax

4
Tôi nghĩ đó có thể là quan điểm của Alex, đó là lý do tại sao anh ấy viết nó bằng cách sử dụng toán tử "bằng với"!
James Bedford

18
Nó giống như tự bắn mình bằng súng trường ... Quên đặt 'var' trước biến của một người và cuối cùng sửa đổi một biến ở đâu đó trong chuỗi phạm vi ... Hãy thử thuyết phục Java / C / Python / v.v. Nhà phát triển JavaScript đáng giá. Hà! Cạm bẫy C / C ++ trông đẹp. Tưởng tượng phải gỡ lỗi JavaScript ... Và một số người làm điều đó, tất nhiên. Và có rất nhiều mã (và không phải mã đơn giản, làm phiền bạn) được viết bằng JavaScript ...
Albus Dumbledore

6
Nếu bạn ở trong phạm vi toàn cầu thì không có gì khác biệt. >> có một sự khác biệt được giải thích trong câu trả lời dưới đây
Max Koretskyi

746

Có một sự khác biệt .

var x = 1 khai báo biến x trong phạm vi hiện tại (còn gọi là bối cảnh thực thi). Nếu khai báo xuất hiện trong một hàm - một biến cục bộ được khai báo; nếu nó trong phạm vi toàn cầu - một biến toàn cục được khai báo.

x = 1, mặt khác, chỉ là một sự phân công tài sản. Đầu tiên nó cố gắng giải quyết xchống lại chuỗi phạm vi. Nếu nó tìm thấy nó ở bất cứ đâu trong chuỗi phạm vi đó, nó sẽ thực hiện chuyển nhượng; nếu nó không tìm thấy x, chỉ sau đó nó mới tạo thuộc xtính trên một đối tượng toàn cục (là đối tượng cấp cao nhất trong chuỗi phạm vi).

Bây giờ, lưu ý rằng nó không khai báo một biến toàn cục, nó tạo ra một thuộc tính toàn cầu.

Sự khác biệt giữa hai loại này là tinh tế và có thể gây nhầm lẫn trừ khi bạn hiểu rằng khai báo biến cũng tạo ra các thuộc tính (chỉ trên Đối tượng biến) và mọi thuộc tính trong Javascript (tốt, ECMAScript) đều có các cờ nhất định mô tả các thuộc tính của chúng - ReadOnly, DontEnum và Đừng bỏ qua.

Vì khai báo biến tạo thuộc tính với cờ DontDelete, nên sự khác biệt giữa var x = 1x = 1(khi được thực thi trong phạm vi toàn cầu) là khai báo biến trước đây - tạo ra thuộc tính DontDelete'able, và sau này không có. Do đó, thuộc tính được tạo thông qua việc gán ẩn này sau đó có thể bị xóa khỏi đối tượng toàn cục và đối tượng cũ - thuộc tính được tạo thông qua khai báo biến - không thể bị xóa.

Nhưng đây chỉ là lý thuyết tất nhiên, và trong thực tế thậm chí còn có nhiều sự khác biệt hơn giữa hai điều này , do các lỗi khác nhau trong việc triển khai (chẳng hạn như các lỗi từ IE).

Hy vọng tất cả có ý nghĩa :)


[Cập nhật 2010/12/16]

Trong ES5 (ECMAScript 5; phiên bản thứ 5 của ngôn ngữ được chuẩn hóa gần đây) có cái gọi là "chế độ nghiêm ngặt" - chế độ ngôn ngữ chọn tham gia, thay đổi một chút hành vi của các bài tập không được khai báo. Trong chế độ nghiêm ngặt, việc gán cho một định danh chưa được khai báo là ReferenceError . Lý do cho việc này là để bắt các nhiệm vụ tình cờ, ngăn chặn việc tạo ra các tài sản toàn cầu không mong muốn. Một số trình duyệt mới hơn đã bắt đầu hỗ trợ cho chế độ nghiêm ngặt. Xem, ví dụ, bảng compat của tôi .


Nếu tôi nhớ lại một cách chính xác, tôi nghĩ rằng tôi đã từng tìm ra cách để có thể deletebiến var-kê khai với một số evalhack. Nếu tôi nhớ thủ thuật chính xác tôi sẽ đăng ở đây.
Tháp

3
@Mageek Anh ấy có thể lấy về các biến khai báo eval có thể xóa được. Tôi đã viết một bài blog về điều này một lần.
kangax

1
Một chút ra khỏi chủ đề, nhưng đề cập đến nó ở đây để tham khảo. "let" rất giống với "var" và được hỗ trợ trong Mozilla. Sự khác biệt chính là phạm vi của một biến var là toàn bộ hàm kèm theo trong đó "let" bị giới hạn trong khối của nó
mac

@ Khangax sẽ thế nào nếu hai dòng ví dụ cuối cùng của Alex bị trộn lẫn: var someObject = {}someObject.someProperty = 5? Sẽ somePropertytrở thành toàn cầu, trong khi đối tượng nó là tài sản của địa phương?
snapfractalpop

1
Tên đặc tả cho cái mà @ Khangax gọi là cờ DontDelete có thể định cấu hình (= false) , bạn có thể đọc về điều này liên quan đến Object.definePropertyObject.getOwnPropertyDescriptor
Paul S.

137

Nói rằng sự khác biệt giữa " địa phươngtoàn cầu " không hoàn toàn chính xác.

Có thể tốt hơn khi nghĩ về nó như là sự khác biệt giữa " địa phươnggần nhất ". Gần nhất chắc chắn có thể là toàn cầu, nhưng điều đó sẽ không luôn luôn như vậy.

/* global scope */
var local = true;
var global = true;

function outer() {
    /* local scope */
    var local = true;
    var global = false;

    /* nearest scope = outer */
    local = !global;

    function inner() {
        /* nearest scope = outer */
        local = false;
        global = false;

        /* nearest scope = undefined */
        /* defaults to defining a global */
        public = global;
    }
}

3
Không phải là phạm vi gần nhất outermà bạn xác định var global = false;?
Snekse

@Snekse: 'gần nhất' không áp dụng khi <code> var global = false; </ code> được khai báo. Trong tuyên bố đó, 'toàn cầu' được đặt trong phạm vi bên ngoài () vì 'var' được sử dụng trong khai báo. Vì 'var' không được sử dụng ở bên trong (), nên nó sẽ thay đổi giá trị ở cấp độ tiếp theo, bên ngoài ().
Mitch

Tôi tự hỏi nếu bạn nhận xét sẽ thay đổi nếu bạn thay đổi dòng đó thành var global = local;trong trường hợp đó phạm vi gần của địa phương sẽ là phạm vi bên ngoài "cục bộ" đang được xác định tích cực. Mặc dù thật lạ nếu bạn thay đổi cùng một dòng thành var global = globaltrường hợp phạm vi gần nhất khi tìm kiếm giá trị globalsẽ tăng lên một mức ở phạm vi cửa sổ toàn cầu.
Snekse

80

Khi Javascript được thực thi trong trình duyệt, tất cả mã của bạn được bao quanh bởi một câu lệnh with, như vậy:

with (window) {
    //Your code
}

Thông tin thêm về with- MDN

varkhai báo một biến trong phạm vi hiện tại , không có sự khác biệt giữa khai báo var bên trong cửa sổ và không khai báo nó.

Sự khác biệt xuất hiện khi bạn không trực tiếp bên trong cửa sổ, ví dụ bên trong một chức năng hoặc bên trong một khối.

Sử dụng varcho phép bạn ẩn các biến bên ngoài có cùng tên. Theo cách này, bạn có thể mô phỏng một biến "riêng tư", nhưng đó là một chủ đề khác.

Một nguyên tắc nhỏ là luôn luôn sử dụng var, bởi vì nếu không, bạn sẽ gặp rủi ro khi đưa ra các lỗi tinh vi.

EDIT: Sau những bài phê bình tôi nhận được, tôi muốn nhấn mạnh những điều sau:

  • varkhai báo một biến trong phạm vi hiện tại
  • Phạm vi toàn cầu là window
  • Không sử dụng varkhai báo ngầm vartrong phạm vi toàn cầu (cửa sổ)
  • Khai báo một biến trong phạm vi toàn cầu (cửa sổ) bằng cách sử dụng vargiống như bỏ qua nó.
  • Khai báo một biến trong phạm vi khác với cửa sổ sử dụng var không giống như khai báo một biến mà không cóvar
  • Luôn luôn tuyên bố varrõ ràng bởi vì đó là thực hành tốt

1
Tôi đã không đánh giá thấp bạn, nhưng phạm vi có lẽ là một từ tốt hơn so với cửa sổ. Toàn bộ lời giải thích của bạn là một chút khó hiểu.
Robert Harvey

4
Tôi chỉ đơn giản gọi mọi thứ với tên của nó, bạn muốn gọi nó là "phạm vi toàn cầu", nhưng không sao, nhưng phía khách hàng, theo quy ước, là đối tượng cửa sổ, đó là yếu tố cuối cùng của chuỗi phạm vi, đó là lý do tại sao bạn có thể gọi mọi thứ chức năng và mọi đối tượng trong cửa sổ mà không ghi "cửa sổ."
kentaromiura

2
+1 đây là một lời giải thích thực sự hay - tôi chưa từng nghe vấn đề var / no var đóng khung (không có ý định chơi chữ) như thế này trước đây.
doug

Hầu hết câu trả lời này không được chấp nhận lettrong ES6.
Evan Carroll

3
@EvanCarroll Câu trả lời này cũng không đúng về mặt kỹ thuật vì bỏ qua var không khai báo bất kỳ biến nào, thay vào đó, nó tạo ra một thuộc tính có thể xóa trên đối tượng toàn cầu, bên cạnh chế độ "sử dụng nghiêm ngặt" ES5, hầu hết câu trả lời rõ ràng là không chính xác, cũng vậy Thậm chí đã xem xét trong câu trả lời này vì tại thời điểm câu hỏi không có bất kỳ tài liệu tham khảo nào về phiên bản javascript (được thêm vào ngày hôm qua) ngụ ý rằng tiêu chuẩn tham chiếu (tại thời điểm đó) là ECMA 262 Phiên bản thứ 3.
kentaromiura

43

Luôn luôn sử dụng vartừ khóa để khai báo các biến. Tại sao? Thực hành mã hóa tốt nên có đủ lý do trong chính nó, nhưng bỏ qua nó có nghĩa là nó được khai báo trong phạm vi toàn cầu (một biến như thế này được gọi là toàn cầu "ngụ ý"). Douglas Crockford khuyến nghị không bao giờ sử dụng toàn cầu ngụ ý và theo Nguyên tắc mã hóa JavaScript của Apple :

Bất kỳ biến nào được tạo mà không có var từ khóa đều được tạo ở phạm vi toàn cục và không phải là rác được thu thập khi hàm trả về (vì nó không nằm ngoài phạm vi), tạo cơ hội cho rò rỉ bộ nhớ.


17
"Thực hành mã hóa tốt" không bao giờ nên có đủ lý do. Nó lên tới "một số kẻ trên internet nói rằng đây là giao diện của mã của tôi". Điều đó thậm chí còn ít hợp lệ hơn "giáo viên của tôi đã nói", trừ khi ít nhất một người mơ hồ hiểu được lý do đằng sau quy tắc này.
cHao

@cHao Tôi nghĩ good coding practiceluôn có đủ lý do nếu đó là một cách thực hành tốt nhất được đề xuất, đây là và bởi một số tác giả Javascript.
Chris S

8
@ChrisS: Không, "thực hành mã hóa tốt" không phải là lý do. Các lý do nó được coi là thực hành tốt là những gì quan trọng. Trừ khi những tác giả đó cho bạn biết lý do tại sao họ giới thiệu nó, khuyến nghị của họ sẽ không mang bất kỳ trọng lượng nào. Nếu bạn không đồng ý với lý do, thì bạn có thể coi đó là lời khuyên tồi. Và nếu bạn làm theo nó mà không bao giờ hỏi tại sao, đó là cách văn hóa hàng hóa bắt đầu.
cHao

30

Đây là một ví dụ điển hình về cách bạn có thể bị bắt gặp khi không khai báo các biến cục bộ với var:

<script>
one();

function one()
{
    for (i = 0;i < 10;i++)
    {
        two();
        alert(i);
    }
}

function two()
{
    i = 1;
}
</script>

( iđược đặt lại ở mỗi lần lặp của vòng lặp, vì nó không được khai báo cục bộ trong forvòng lặp mà trên toàn cầu) cuối cùng dẫn đến vòng lặp vô hạn


Rất tiếc! Tôi chỉ có thể tưởng tượng tất cả các lỗi có thể được gây ra bởi lỗi đánh máy đó.
bonsaiOak

2
Tôi tò mò, tại sao bạn lại chuyển tôi làm đối số cho hai ()? (bên trong vòng lặp for) có dư không?
kalin

Đối số được bỏ qua trong hàm hai () được gói gọn trong hàm một (), vì hàm hai () được xác định không có tham số. Bạn khá chính xác, Nó không cần thiết vì nó không đóng vai trò.
KK.

Lỗi hay tính năng?
TheMaster

13

Tôi sẽ nói rằng tốt hơn để sử dụng vartrong hầu hết các tình huống.

Các biến cục bộ luôn nhanh hơn các biến trong phạm vi toàn cầu.

Nếu bạn không sử dụng varđể khai báo một biến, biến đó sẽ nằm trong phạm vi toàn cầu.

Để biết thêm thông tin, bạn có thể tìm kiếm "JavaScript chuỗi phạm vi" trong Google.


Nếu bạn khai báo một biến bằng cách sử dụng từ khóa var, nó sẽ được tạo khi chạy vì vậy nó có nên chậm hơn không? Bởi vì một cái khác được tạo ra tại thời điểm phân tích cú pháp.
Barış Velioğlu

@RyuKaplan - này, điều đó có đúng không? Tôi đã thử googling và không thể có bất kỳ thông tin nào về chủ đề này! Bạn có một cơ quan nguồn cho khẳng định đó? Thx
loài gặm nhấm mike

@RyuKaplan Phân tích cú pháp / biên dịch khác với thực tế chạy mã.
gcampbell

11

Đừng sử dụng var!

varlà cách trước ES6 để khai báo một biến. Chúng tôi đang ở trong tương lai và bạn nên viết mã như vậy.

Sử dụng constlet

constnên được sử dụng cho 95% các trường hợp. Nó làm cho nó để tham chiếu biến không thể thay đổi, do đó các thuộc tính của mảng, đối tượng và nút DOM có thể thay đổi và có thể sẽ thay đổi const.

letnên được sử dụng cho bất kỳ biến nào được mong đợi được gán lại. Điều này bao gồm trong một vòng lặp for. Nếu bạn từng viết varName =vượt quá khởi tạo, hãy sử dụng let.

Cả hai đều có phạm vi cấp khối, như mong đợi trong hầu hết các ngôn ngữ khác.


2
Thay thế tất cả bạn 'var' bằng 'const' (thay thế tất cả). Bạn sẽ nhanh chóng nhận thấy các biến được gán lại của bạn ở đâu. Nếu bạn có quá nhiều trong số chúng, bạn có thể mã chống mẫu: hầu hết các biến có thể gán lại có thể được nhúng trong các bao đóng hoặc dưới dạng các thuộc tính đối tượng. Nếu bạn có một vài: sử dụng 'cho phép' cho họ. Cuối cùng, nếu một số biến không hoàn toàn không thích với 'var', chúng sẽ không được khai báo và vẫn hiện diện trong không gian toàn cầu, hãy cẩn thận. Về nhận xét @Gibolt 'trong vòng lặp for', bạn cũng nên tránh các vòng lặp như vậy trong "95% trường hợp" ;-): phương thức mảng rất tuyệt.
allez

Bằng cách nói rằng const nên được sử dụng trong 95% các trường hợp, có vẻ như chúng ta sẽ tránh xa thực tiễn tốt và thành giáo điều.
Agamemnus

9

sự khác biệt khác, vd

var a = a || [] ; // works 

trong khi

a = a || [] ; // a is undefined error.

1
Bạn có thể giải thích tại sao nó hoạt động trong trường hợp biến được xác định bằng 'var' và biến không được xác định bằng var? Là biến được tạo trước khi đánh giá bên phải của bài tập trong trường hợp var?
matt

6
@Lucek vì var ađược nâng lên trên cùng của phạm vi và được đặt thành null mà khai báo nhưng không khởi tạo biến, sau đó, trong bài tập, bạn có một tham chiếu đến một biến null không xác định sẽ đánh giá thành false và đặt phép gán thành []. Sau này, bạn có một sự phân công cho tài sản acủa tài sản a. Bạn có thể gán cho một thuộc tính không tồn tại - tạo nó trên chuyển nhượng, nhưng bạn không thể đọc từ một thuộc tính không tồn tại mà không ReferenceErrorbị ném vào bạn.
Evan Carroll

1
@EvanCarroll: nó được đưa lên đầu phạm vi và được đặt thành không xác định thay vì null.
mithuneditesh

8

Sử dụng varluôn là một ý tưởng tốt để ngăn chặn các biến làm lộn xộn phạm vi toàn cầu và các biến không xung đột với nhau, gây ra ghi đè không mong muốn.


8

Không có var - biến toàn cầu.

Rất khuyến khích LUÔN LUÔN sử dụng varcâu lệnh, bởi vì biến toàn cục init trong bối cảnh cục bộ - là xấu xa. Nhưng, nếu bạn cần thủ thuật bẩn này, bạn nên viết bình luận ở đầu trang:

/* global: varname1, varname2... */

3

Đây là mã ví dụ tôi đã viết để bạn hiểu khái niệm này:

var foo = 5; 
bar = 2;     
fooba = 3;

// Execute an anonymous function
(function() {    
    bar = 100;             //overwrites global scope bar
    var foo = 4;           //a new foo variable is created in this' function's scope
    var fooba = 900;       //same as above
    document.write(foo);   //prints 4
    document.write(bar);   //prints 100
    document.write(fooba); //prints 900
})();

document.write('<br/>');
document.write('<br/>');
document.write(foo);       //prints 5
document.write(bar);       //prints 100
document.write(fooba);     //prints 3

2
Chức năng này không có nghĩa là "ẩn danh". Trong thực tế, nó được đặt tên rõ ràng như nó có thể có thể.
Ingo Bürk

Cảm ơn bạn đã chỉnh sửa câu trả lời của mình, để phản hồi bình luận của Ingo Bürk, để làm cho "chức năng ẩn danh" thực sự ẩn danh.
Dave Burton

3

@Chris S đã đưa ra một ví dụ hay cho thấy sự khác biệt thực tế (và nguy hiểm) giữa varvà khôngvar . Đây là một cái khác, tôi thấy cái này đặc biệt nguy hiểm vì sự khác biệt chỉ có thể nhìn thấy trong một môi trường không đồng bộ để nó có thể dễ dàng bị trượt trong quá trình thử nghiệm.

Như bạn mong đợi các đầu ra đoạn mã sau ["text"]:

function var_fun() {
  let array = []
  array.push('text')
  return array
}

console.log(var_fun())

Đoạn mã sau cũng vậy (lưu ý phần còn thiếu lettrước array):

function var_fun() {
  array = []
  array.push('text')
  return array
}

console.log(var_fun())

Thực hiện thao tác dữ liệu không đồng bộ vẫn tạo ra kết quả tương tự với một người thực thi:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

var_fun().then(result => {console.log(result)})

Nhưng hành xử khác nhau với nhiều người:

function var_fun() {
  array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})

Tuy nhiên, sử dụng let:

function var_fun() {
  let array = [];
  return new Promise(resolve => resolve()).then(() => {
    array.push('text')
    return array
  })
}

[1,2,3].forEach(i => {
  var_fun().then(result => {console.log(result)})
})


Cảm ơn ví dụ @thisismydesign! Liên quan đến hai ví dụ cuối cùng, tại sao ví dụ áp chót ghi lại một mảng gồm 3 phần tử với văn bản ba lần trong khi ví dụ cuối cùng chỉ ghi lại "văn bản" một lần cho mỗi phần tử trong mảng? (Tôi hiểu rằng cái cuối cùng tuyên bố "mảng" là một biến và do đó nằm trong phạm vi cục bộ, trong khi ví dụ áp chót bỏ qua điều này, làm cho "mảng" trở thành một phần của phạm vi toàn cầu ngụ ý.) Nhưng, tại sao điều này ảnh hưởng đến đầu ra? Có phải vì forEach "i" lặp lại hàm và tất cả các biến toàn cục?
MostPitt

2

Như một người nào đó đang cố gắng học điều này thì đây là cách tôi nhìn thấy nó. Các ví dụ trên có thể hơi phức tạp đối với người mới bắt đầu.

Nếu bạn chạy mã này:

var local = true;
var global = true;


function test(){
  var local = false;
  var global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Đầu ra sẽ đọc là: false, false, true, true

Bởi vì nó thấy các biến trong hàm là tách biệt với các biến bên ngoài nó, do đó thuật ngữ biến cục bộ và điều này là do chúng ta đã sử dụng var trong bài tập. Nếu bạn lấy đi var trong hàm thì bây giờ nó sẽ đọc như sau:

var local = true;
var global = true;


function test(){
  local = false;
  global = false;
  console.log(local)
  console.log(global)
}

test();

console.log(local);
console.log(global);

Đầu ra là sai, sai, sai, sai

Điều này là do thay vì tạo một biến mới trong phạm vi hoặc hàm cục bộ, nó chỉ đơn giản sử dụng các biến toàn cục và gán lại chúng thành false.


2

Tôi thấy mọi người bối rối khi khai báo các biến có hoặc không có var và bên trong hoặc bên ngoài hàm. Dưới đây là một ví dụ sâu sắc sẽ đưa bạn qua các bước sau:

Xem kịch bản dưới đây trong hành động ở đây tại jsfiddle

a = 1;// Defined outside the function without var
var b = 1;// Defined outside the function with var
alert("Starting outside of all functions... \n \n a, b defined but c, d not defined yet: \n a:" + a + "\n b:" + b + "\n \n (If I try to show the value of the undefined c or d, console.log would throw 'Uncaught ReferenceError: c is not defined' error and script would stop running!)");

function testVar1(){
    c = 1;// Defined inside the function without var
    var d = 1;// Defined inside the function with var
    alert("Now inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 1. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};


testVar1();
alert("Run the 1. function again...");
testVar1();

function testVar2(){
    var d = 1;// Defined inside the function with var
    alert("Now inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);

    a = a + 5;
    b = b + 5;
    c = c + 5;
    d = d + 5;

    alert("After added values inside the 2. function: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n d:" + d);
};

testVar2();

alert("Now outside of all functions... \n \n Final Values: \n a:" + a + "\n b:" + b + "\n c:" + c + "\n You will not be able to see d here because then the value is requested, console.log would throw error 'Uncaught ReferenceError: d is not defined' and script would stop. \n ");
alert("**************\n Conclusion \n ************** \n \n 1. No matter declared with or without var (like a, b) if they get their value outside the function, they will preserve their value and also any other values that are added inside various functions through the script are preserved.\n 2. If the variable is declared without var inside a function (like c), it will act like the previous rule, it will preserve its value across all functions from now on. Either it got its first value in function testVar1() it still preserves the value and get additional value in function testVar2() \n 3. If the variable is declared with var inside a function only (like d in testVar1 or testVar2) it will will be undefined whenever the function ends. So it will be temporary variable in a function.");
alert("Now check console.log for the error when value d is requested next:");
alert(d);

Phần kết luận

  1. Bất kể được khai báo có hoặc không có var (như a, b) nếu chúng nhận được giá trị bên ngoài hàm, chúng sẽ bảo toàn giá trị của chúng và bất kỳ giá trị nào khác được thêm vào bên trong các hàm khác nhau thông qua tập lệnh được giữ nguyên.
  2. Nếu biến được khai báo không có var bên trong một hàm (như c), nó sẽ hoạt động như quy tắc trước đó, nó sẽ bảo toàn giá trị của nó trên tất cả các hàm kể từ bây giờ. Hoặc nó có giá trị đầu tiên trong hàm testVar1 () nó vẫn giữ giá trị và nhận giá trị bổ sung trong hàm testVar2 ()
  3. Nếu biến chỉ được khai báo với var bên trong một hàm (như d trong testVar1 hoặc testVar2) thì nó sẽ không được xác định bất cứ khi nào hàm kết thúc. Vì vậy, nó sẽ là biến tạm thời trong một chức năng.

Cảm ơn đã dành thời gian để tạo một ví dụ để chứng minh chủ đề này. Đoạn mã trên thiếu phần bên dưới, vì vậy bạn có thể muốn chỉnh sửa câu trả lời của mình: a = 1; // Được xác định bên ngoài hàm mà không var var b = 1; // Được xác định bên ngoài hàm với cảnh báo var ("Bắt đầu bên ngoài tất cả các hàm ... \ n \ na, b đã xác định nhưng c, d chưa được xác định: \ na: "+ a +" \ nb: "+ b +" \ n \ n (Nếu tôi cố gắng hiển thị giá trị của c không xác định hoặc d, console.log sẽ ném 'Uncaught ReferenceError: c không được xác định' và tập lệnh sẽ ngừng chạy!) ");
Sankofa

1

Bên trong một mã bạn nếu bạn sử dụng một biến mà không sử dụng var, thì điều xảy ra là var var_name tự động được đặt trong phạm vi toàn cục, ví dụ:

someFunction() {
    var a = some_value; /*a has local scope and it cannot be accessed when this
    function is not active*/
    b = a; /*here it places "var b" at top of script i.e. gives b global scope or
    uses already defined global variable b */
}

1

Bên cạnh vấn đề phạm vi, một số người cũng đề cập đến cẩu , nhưng không ai đưa ra một ví dụ. Đây là một cho phạm vi toàn cầu:

console.log(noErrorCase);
var noErrorCase = "you will reach that point";

console.log(runTimeError);
runTimeError = "you won't reach that point";


0

Không sử dụng biến "var" chỉ có thể xác định khi đặt giá trị. Trong ví dụ:

my_var;

không thể làm việc trong phạm vi toàn cầu hoặc bất kỳ phạm vi khác . Nó nên có giá trị như:

my_var = "value";

Mặt khác, bạn có thể định nghĩa một khả năng thích;

var my_var;

Giá trị của nó là undefined(Giá trị của nó là không nullvà nó không bằng nullthú vị.).


my_var;thực sự là một tuyên bố biểu thức hợp lệ.
lexicore

Đó là tuyên bố hợp lệ nếu biến được xác định trước. Nếu không, nó sẽ báo lỗi "... không được xác định".
umut

3
Đó là một tuyên bố hợp lệ bất kể một biến đã được xác định trước hay chưa. :) Một tuyên bố hợp lệ có thể ném một eror nó không làm cho tuyên bố không hợp lệ.
lexicore

Tôi bối rối về nó. Tuyên bố hợp lệ là gì? Và bạn có thể cho tôi một ví dụ tuyên bố không hợp lệ?
umut

Tôi sẽ phải xin lỗi - gần đây quá nhiều ngữ pháp ECMAScript. my_var;là một tuyên bố biểu thức hợp lệ . /my_var;sẽ là một tuyên bố không hợp lệ. Nhưng như tôi đã nói, đây là ngữ pháp ngữ pháp, tôi xin lỗi, nhận xét của tôi thực sự không phù hợp.
lexicore

0

Bạn nên sử dụng từ khóa var trừ khi bạn có ý định gắn biến đối tượng vào cửa sổ trong trình duyệt. Đây là một liên kết giải thích phạm vi và sự khác biệt giữa phạm vi glocal và phạm vi cục bộ với và từ khóa var không có.

Khi các biến được xác định mà không sử dụng từ khóa var, nó trông giống như một hoạt động chuyển nhượng đơn giản.

Khi giá trị được gán cho một biến trong javascript, trước tiên, trình thông dịch sẽ cố gắng tìm ra khai báo biến số biến đổi trong cùng một bối cảnh / phạm vi như của phép gán. Khi trình thông dịch thực thi dummyVariable = 20, nó tìm kiếm khai báo của dummyVariable khi bắt đầu hàm. (Vì tất cả các khai báo Biến được chuyển đến đầu ngữ cảnh bởi trình thông dịch javascript và điều này được gọi là cẩu

Bạn cũng có thể muốn nhìn vào cẩu trong javascript

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.