2013-05-14 25 views
8

Giả sử tôi đã đoạn mã sau (hoàn toàn vô dụng, tôi biết)Có an toàn để vượt qua 'tranh luận' thành 'apply()'

function add(a, b, c, d) { 
    alert(a+b+c+d); 
} 

function proxy() { 
    add.apply(window, arguments); 
} 

proxy(1,2,3,4); 

Về cơ bản, chúng ta biết rằng áp dụng hy vọng một mảng là tham số thứ hai nhưng chúng tôi cũng biết rằng arguments không phải là một mảng phù hợp. Mã hoạt động như mong đợi, vì vậy có an toàn khi nói rằng tôi có thể truyền bất kỳ đối tượng giống mảng nào như tham số thứ hai trong apply() không?

Sau đây cũng sẽ làm việc (trong Chrome ít nhất):

function proxy() { 
    add.apply(window, { 
    0: arguments[0], 
    1: arguments[1], 
    2: arguments[2], 
    3: arguments[3], 
    length: 4 
    }); 
} 

Cập nhật: Dường như khối mã thứ hai của tôi thất bại trong IE < 9 trong khi người đầu tiên (đi qua arguments) hoạt động. Lỗi là Array or arguments object expected, vì vậy chúng tôi sẽ kết luận rằng luôn an toàn khi vượt qua arguments, trong khi không an toàn để truyền đối tượng giống mảng trong oldIE.

+1

Tại sao _không phải là "an toàn"? – Neal

+0

@Neal well 'arguments' là một con thú khá kỳ lạ, do đó, một số lo lắng về việc sử dụng nó không phải là không hợp lý. Trong trường hợp này tôi không thể tưởng tượng được nó sẽ là vấn đề như thế nào. – Pointy

+0

@Neal, có thể vì 'đối số' không có nhiều phương thức mà Mảng bình thường có và' .apply' có thể muốn sử dụng chúng? – Dogbert

Trả lời

3

Giả sử ECMAScript 5.1: Có. Theo ECMA-262, 10.6, đối tượng đối số có các thuộc tính length và chỉ mục 15.3.4.3 (Function.prototype.apply) yêu cầu.

+0

Đây là câu trả lời ngắn nhất nhưng thực sự là rất chính xác về vấn đề an toàn .. bạn có biết tại sao mã thử nghiệm thứ hai của tôi không thành công không ECMASCRIPT 5 IE (

+2

oh IE nói rõ ràng: 'Mảng hoặc đối số đối tượng được mong đợi' vì vậy tôi đoán là an toàn để chuyển' đối số', không an toàn để truyền đối tượng giống mảng –

7

Từ định nghĩa của Function.prototype.apply trong MDN:

fun.apply(thisArg[, argsArray])

Bạn cũng có thể sử dụng arguments cho tham số argsArray. arguments là một biến số địa phương của hàm . Nó có thể được sử dụng cho tất cả các đối số không xác định của đối tượng được gọi. Do đó, bạn không cần phải biết đối số của đối tượng được gọi khi bạn sử dụng phương thức apply. Bạn có thể sử dụng arguments để chuyển tất cả các đối số cho đối tượng được gọi. Đối tượng được gọi là sau đó chịu trách nhiệm xử lý các đối số.

REF:https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/apply

Như đối số thứ hai apply chấp nhận "một mảng như đối tượng, xác định các đối số mà chức năng nên được gọi là". Theo hiểu biết của tôi, đối tượng giống mảng này phải có thuộc tính length để lặp lại nội bộ và số lượng các thuộc tính được xác định (không được lập chỉ mục) để truy cập các giá trị.

Và điều tương tự được xác nhận của tôi spec: http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.3, như đã được chỉ ra bởi @Pointy.

+2

Ngoài ra [phần 15.3.4.3 của thông số] (http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.3) làm cho nó rõ ràng rõ ràng 'apply' chỉ xem xét giá trị' length' và thuộc tính được đánh số (được lập chỉ mục). – Pointy

+0

@Pointy Tôi cho rằng nó * nên * hoạt động theo cách này ':)' – VisioN

1

MDN chỉ có thể nói cho việc triển khai Mozilla. Thực tế spec mà tất cả hiện thực phải tuân thủ nói như sau:

15.3.4.3 Function.prototype.apply (thisArg, argArray) 

When the apply method is called on an object func with arguments thisArg and 
argArray, the following steps are taken: 

1. If IsCallable(func) is false, then throw a TypeError exception. 
2. If argArray is null or undefined, then 
     Return the result of calling the [[Call]] internal method of func, 
     providing thisArg as the this value and an empty list of arguments. 
3. If Type(argArray) is not Object, then throw a TypeError exception. 
4. Let len be the result of calling the [[Get]] internal method of argArray 
     with argument "length". 
5. If len is null or undefined, then throw a TypeError exception. 
6. Let n be ToUint32(len). 
7. If n is not equal to ToNumber(len), then throw a TypeError exception. 
8. Let argList be an empty List. 
9. Let index be 0. 
10. Repeat while index < n 
     a. Let indexName be ToString(index). 
     b. Let nextArg be the result of calling the [[Get]] internal method of 
     argArray with indexName as the argument. 
     c. Append nextArg as the last element of argList. 
     d. Set index to index + 1. 
11. Return the result of calling the [[Call]] internal method of func, 
     providing thisArg as the this value and argList as the list of arguments. 

The length property of the apply method is 2. 

NOTE The thisArg value is passed without modification as the this value. This 
    is a change from Edition 3, where an undefined or null thisArg is replaced 
    with the global object and ToObject is applied to all other values and that 
    result is passed as the this value. 

Dường như bất động sản và chỉ số length số giá trị là những điều kiện tiên quyết mà thôi.

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