Chuyển nhượng nhiều bên trái với JavaScript


186
var var1 = 1,
    var2 = 1,
    var3 = 1;

Điều này tương đương với điều này:

var var1 = var2 = var3 = 1;

Tôi khá chắc chắn đây là thứ tự các biến được định nghĩa: var3, var2, var1, tương đương với điều này:

var var3 = 1, var2 = var3, var1 = var2;

Có cách nào để xác nhận điều này trong JavaScript không? Sử dụng một số hồ sơ có thể?


6
CHUYỂN NHƯỢNG XẢY RA phải sang trái javascript điều hành được ưu tiên
neaumusic

điều này cũng được áp dụng nếu tôi sử dụng this.var1 = this.var2 = this.var3 = 1?
Gangadhar JANNU

Câu trả lời:


404

Thực ra,

var var1 = 1, var2 = 1, var3 = 1;

không tương đương với:

var var1 = var2 = var3 = 1;

Sự khác biệt là trong phạm vi:

function good() {
  var var1 = 1, var2 = 1, var3 = 1;
}

function bad() {
  var var1 = var2 = var3 = 1;
}

good();
console.log(window.var2); // undefined

bad();
console.log(window.var2); // 1. Aggh!

Trên thực tế điều này cho thấy sự phân công là kết hợp đúng. Các badví dụ là tương đương với:

var var1 = (window.var2 = (window.var3 = 1));

44
Dang, thật bất ngờ. Cảm ơn vì tiền boa, tôi sẽ coi chừng điều đó.
David Calhoun

10
@ SkinnyG33k vì nó phải sang trái. vì vậy nó sẽ phân tích cú pháp bên phải nhiều nhất trước bên trái nhất. vì vậy var var1=var2xảy ra sau var3 = 1và sauvar2 = var3 . nó giống nhưvar3=1; var2=var3; var var1=var2
gcb

12
Chỉ cần lưu ý: nếu bạn biết bạn muốn làm điều này trước thời hạn, bạn vẫn có thể phá vỡ định nghĩa từ bài tập. Vì vậy: var v1, v2, v3;Sau đó, sau này: v1 = v2 = v3 = 6;Họ sẽ vẫn ở trong phạm vi địa phương. Vì David đã đề cập đến các cảnh báo, điều này sẽ hoạt động như mong đợi (nếu trước đó):alert(v1 = v2 = v3 = 6);
ShawnFumo

3
Chính xác. Nhưng nếu chúng ta tuân theo một số thực tiễn tốt nhất phổ biến, trong trường hợp này bằng cách khai báo các biến của chúng ta ở đầu, chúng ta có thể tránh được các lỗi không mong muốn và tránh các biến cục bộ bị rò rỉ ra phạm vi toàn cầu. Xem: jsfiddle.net/gleezer/r9Mu8/1
Nobita

1
"Dang, thật bất ngờ." Tại sao điều này sẽ bất ngờ? Hầu hết các ngôn ngữ yêu cầu bạn khai báo các biến của bạn trước khi sử dụng. JavaScript không khác, nếu bạn bỏ qua việc khai báo biến của mình thì nó mặc định là đối tượng cửa sổ chung. Bắt đầu sử dụng 'sử dụng nghiêm ngặt' trong javascript của bạn và bạn sẽ trở thành một lập trình viên JavaScript tốt hơn.
cchamberlain

19

Bài tập trong javascript hoạt động từ phải sang trái. var var1 = var2 = var3 = 1;.

Nếu giá trị của bất kỳ của các biến là 1sau tuyên bố này, sau đó một cách logic nó phải bắt đầu từ bên phải, nếu không giá trị hoặc var1var2sẽ được xác định.

Bạn có thể nghĩ về nó tương đương với var var1 = (var2 = (var3 = 1));nơi tập hợp dấu ngoặc đơn bên trong nhất được đánh giá đầu tiên.


1
Cảm ơn, điều này chắc chắn giúp. Nó giúp suy nghĩ về những lỗi sẽ được ném nếu nó được đánh giá khác với từ phải sang trái (trong trường hợp này, lỗi sẽ là var1 / var2 không được xác định).
David Calhoun

5
Đó thực sự là một lỗi cú pháp. Bạn không thể có (ngay sau đó var. Loại bỏ bộ dấu ngoặc đơn bên ngoài cho phép nó biên dịch mà không có lỗi , var var1 = (var2 = (var3 = 1));. Vào thời điểm đó, tôi cảm thấy rằng nó không minh họa điểm khá tốt, nhưng tôi cho rằng nó giống nhau.
Justin Johnson

var var1 = var2 = var3 = 1;. bằng var var3 = 1; var var2 = var3; var var1 = var2;
xgqfrms

8

var var1 = 1, var2 = 1, var3 = 1;

Trong trường hợp này, vartừ khóa được áp dụng cho cả ba biến.

var var1 = 1,
    var2 = 1,
    var3 = 1;

không tương đương với điều này:

var var1 = var2 = var3 = 1;

Trong trường hợp này phía sau màn hình varkhóa là chỉ áp dụng đối với var1Do cẩu biến và nghỉ ngơi của biểu thức được đánh giá thông thường nên các biến var2, var3đang trở nên globals

Javascript xử lý mã này theo thứ tự này:

/*
var 1 is local to the particular scope because of var keyword
var2 and var3 will become globals because they've used without var keyword
*/

var var1;   //only variable declarations will be hoisted.

var1= var2= var3 = 1; 

8
a = (b = 'string is truthy'); // b gets string; a gets b, which is a primitive (copy)
a = (b = { c: 'yes' }); // they point to the same object; a === b (not a copy)

(a && b)là logic (a ? b : a)và hoạt động như phép nhân (ví dụ. !!a * !!b)

(a || b)là hợp lý (a ? a : b)và hành xử như bổ sung (ví dụ. !!a + !!b)

(a = 0, b)là viết tắt của việc không quan tâm nếu alà sự thật, hoàn toàn trở lạib


a = (b = 0) && "nope, but a is 0 and b is 0"; // b is falsey + order of operations
a = (b = "b is this string") && "a gets this string"; // b is truthy + order of ops

Ưu tiên toán tử JavaScript (Trình tự hoạt động)

Lưu ý rằng toán tử dấu phẩy thực sự là toán tử ít đặc quyền nhất, nhưng dấu ngoặc đơn là đặc quyền nhất và chúng song hành với nhau khi xây dựng các biểu thức một dòng.


Cuối cùng, bạn có thể cần 'thunks' thay vì các giá trị được mã hóa cứng và đối với tôi, một thunk vừa là chức năng vừa là giá trị kết quả (cùng một 'điều').

const windowInnerHeight = () => 0.8 * window.innerHeight; // a thunk

windowInnerHeight(); // a thunk

4

Thử cái này:

var var1=42;
var var2;

alert(var2 = var1); //show result of assignment expression is assigned value
alert(var2); // show assignment did occur.

Lưu ý dấu '=' trong cảnh báo đầu tiên. Điều này sẽ cho thấy kết quả của biểu thức gán là giá trị được gán và cảnh báo thứ 2 sẽ cho bạn thấy rằng việc chuyển nhượng đã xảy ra.

Nó tuân theo logic rằng sự phân công phải được xâu chuỗi từ phải sang trái. Tuy nhiên, vì đây là tất cả nguyên tử đối với javascript (không có luồng), một công cụ cụ thể có thể chọn để thực sự tối ưu hóa nó một chút khác nhau.


1
Cảm ơn câu trả lời. Tôi nghĩ rằng tôi đang tìm cách sử dụng các cảnh báo trong khi vẫn duy trì cấu trúc nhiều nhiệm vụ (a = b = c), nhưng tôi không nghĩ điều đó là có thể.
David Calhoun

1
Các câu lệnh riêng lẻ như thế trong javascript (và, mặc dù một vài biểu thức, tất cả đều hoạt động theo một câu lệnh) có thể được coi là nguyên tử. Bạn sẽ phải phá vỡ nó.
Joel Coehoorn

1

Bây giờ rõ ràng là chúng không giống nhau. Cách mã hóa đó là

var var1, var2, var3
var1 = var2 = var3 = 1

Và, những gì về cho phép ám sát? Chính xác giống như var, đừng để sự ám sát làm bạn bối rối vì phạm vi chặn.

let var1 = var2 = 1 // here var2 belong to the global scope

Chúng ta có thể làm như sau:

let v1, v2, v3
v1 = v2 = v3 = 2

Lưu ý: btw, tôi không khuyên bạn nên sử dụng nhiều bài tập, thậm chí không nhiều khai báo trong cùng một dòng.


-3

coffee-script có thể thực hiện điều này với aplomb ..

for x in [ 'a', 'b', 'c' ] then "#{x}" : true

[ { a: true }, { b: true }, { c: true } ]


7
Điều này không thực sự trả lời câu hỏi. Xin vui lòng đọc lại câu hỏi.
Martin

30
ai quan tâm đến cà phê
neaumusic
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.