2011-06-22 34 views
12

Điều này có hợp pháp không? Và nó có hoạt động trên tất cả các trình duyệt không?Đây có phải là javascript hợp pháp không? Việc chuyển đối số cho hàm và thay đổi đối số là

function func1(a, b, c) { 
    //b == 2 here 
    change_em(arguments); 
    //b should equal 3 here 
} 

function change_em(args) { 
    args[0] = 6; 
    args[1]++; 
    args[2] = []; 
} 

func1('foo', 2); 

Nếu bạn thắc mắc, tôi cần điều chỉnh đối số trong hàm. Một macro sẽ là hoàn hảo, ngoại trừ javascript không có. Làm đúng cách, tức là truyền các biến cho một hàm, sau đó trả về các biến trong một đối tượng và sau đó giải nén chúng trong người gọi sẽ gần như nhiều mã như chỉ sao chép/dán hàm điều chỉnh.

Trả lời

12

Nó hợp lệ theo EcmaScript 3 và EcmaScript 5 không nghiêm ngặt, nhưng không hợp lệ trong chế độ nghiêm ngặt EcmaScript 5. Nó hoạt động trong tất cả các trình duyệt hiện đại và hầu hết các trình duyệt cũ. Nó không hoạt động ở chế độ nghiêm ngặt như khi chạy trong Firefox 5 với chỉ thị "use strict".

Từ phần EcmaScript 5 spec 10.6.11.c.ii

10,6 Arguments Object

...

Nếu đúng là sai và tên không phải là một phần tử của mappedNames, sau đó

  1. Thêm tên làm phần tử của danh sách được ánh xạNames.

  2. Cho phép g là kết quả của việc gọi hoạt động trừu tượng MakeArgGetter với đối số tên và env.

  3. Cho p là kết quả của việc gọi hoạt động trừu tượng MakeArgSetter với đối số tên và env.

  4. Gọi phương thức nội bộ của [[DefineOwnProperty]] của bản đồ đi qua ToString (indx), Trình mô tả thuộc tính {[[Set]]: p, [[Get]]: g, [[Configurable]]: true } và giả làm đối số .

Về cơ bản, đối tượng arguments được một setter cho mỗi chỉ số để gán cho arguments[i] thay đổi giá trị của tham số có tên ở vị trí i. Có ngôn ngữ trong spec đó làm cho nó hoạt động ngược lại.

này nên làm việc ở chế độ không nghiêm ngặt trong bất kỳ phiên dịch

(function (x) { 
    alert("x=" + x + ", arguments[0]=" + arguments[0]); // Both should be 0 
    arguments[0] = 1; 
    alert("x=" + x + ", arguments[0]=" + arguments[0]); // both should be 1 
    x = 2; 
    alert("x=" + x + ", arguments[0]=" + arguments[0]); // both should be 2 
})(0); 

Nhưng nếu bạn chạy trên trên Firefox 5 với việc sử dụng chỉ thị nghiêm ngặt bạn nhận được hành vi khác nhau:

(function (x) { 
    "use strict"; 

    alert("x=" + x + ", arguments[0]=" + arguments[0]); // Both should be 0 
    arguments[0] = 1; 
    alert("x=" + x + ", arguments[0]=" + arguments[0]); // x=0, arguments[0]=1 
    x = 2; 
    alert("x=" + x + ", arguments[0]=" + arguments[0]); // x=2, arguments[0]=1 
})(0); 
+0

+1 nhưng sẽ vẫn tốt nếu có một số liên kết đến các tiêu chuẩn áp dụng –

+0

@James Khoury. Sẽ làm. –

+0

@mike Wow thật nhanh! Lời giải thích tuyệt vời nữa, một số người trong chúng ta cần nó. ;) –

0

Xem chỉnh sửa bên dưới – điều này không áp dụng cho câu hỏi này, nhưng vẫn đúng: Trong JavaScript, chỉ các loại phức tạp (đối tượng và mảng) mới được chuyển. Các kiểu nguyên thủy (chuỗi, số và boolean) được truyền theo giá trị; thay đổi một tham số sẽ chỉ ảnh hưởng đến biến đó trong hàm cục bộ.

var primitive = 1; 
var complex = { prop: 1 }; 

function func1() { 
    change(primitive, complex); 
    // primitive == 1 
    // complex == { prop: 2 } 
} 

function change(a,b) { 
    a++; 
    b.prop++; 
} 


Edit: tôi bị mất rằng bạn đang đi qua các đối tượng arguments. A quick test mang lại kết quả tương tự trong Chrome 13, IE 9, Firefox 4 và Opera 10.62.

+1

Vui lòng đọc lại mã của tôi. Tôi không đi qua một kiểu nguyên thủy, tôi đang truyền đối tượng đối số. – Ariel

+0

@Ariel: Rất tiếc, đã bỏ lỡ điều đó; lấy làm tiếc. – josh3736

0

Vâng, nơi "tất cả các trình duyệt" là danh sách hợp lý các trình duyệt hiện đại, được bật Javascript.

1

arguments là một đối tượng giống như mảng, nhưng dù sao cũng là một đối tượng. Vì vậy, khi bạn chuyển nó như một tham số cho một hàm khác, nó sẽ được chuyển qua tham chiếu. Do đó, khi bạn thay đổi bất kỳ giá trị nào, chúng cũng sẽ thay đổi trong đối tượng arguments gốc. Vì vậy, điều này sẽ làm việc như bạn đề xuất. Theo như tôi biết các đối tượng truyền qua tham chiếu được hỗ trợ trong tất cả các trình duyệt, tuy nhiên trong chế độ nghiêm ngặt ECMaScript 5, đối tượng chỉ mục đối số được đặt tên không tự động ánh xạ tới các tham số chính thức được đặt tên nữa.

0

c không được chuyển vào khi gọi func1(), nó sẽ không được đưa vào đối số. Để thiết lập args[2] = [] trong change_em() cũng sẽ không được đặt c trong chức năng chính.

Các vấn đề liên quan