2012-05-04 31 views
10

Tôi có đối tượng có mảng là giá trị.JSHint sẽ không cho phép tôi sử dụng 'forEach' trong vòng lặp 'for'

people = { 
    'steve':['foo','bar'], 
    'joe':['baz','boo'] 
} 

Đối với mỗi khóa, tôi muốn lặp lại các giá trị trong mảng tương ứng. đủ đơn giản:

for (var person in people) { 
    person.forEach(function(item) { 
     console.log(item) 
    }) 
} 

Nhưng JSHint phàn nàn:

Don't make functions within a loop. 

Đây có phải là thực sự là một vấn đề với mã của tôi? Tôi khá thích cú pháp vòng lặp ES5 ngắn. Tôi có cần sử dụng kiểu ES3 hoặc thay đổi mã của mình theo cách khác không?

Trả lời

18

Có hai vấn đề ở đó, một vấn đề mà JSHint đang cảnh báo bạn và một điều cơ bản hơn.

Điều JSHint cảnh báo bạn về lý thuyết là mỗi lần vòng lặp đó chạy, một hàm mới được tạo. Đây sẽ là tốt hơn:

for (var person in people) { 
    person.forEach(handlePerson); 
} 
function handlePerson(item) { 
    console.log(item) 
} 

tôi nói "về mặt lý thuyết" vì mặc dù spec đòi hỏi một đối tượng hàm mới được tạo ra mỗi lần, điều đó không có nghĩa là động cơ không thể tái sử dụng cơ bản thực hiện của hàm, và nó không có nghĩa là các công cụ không thể tái sử dụng cùng một đối tượng hàm nếu bạn không gán bất kỳ thuộc tính nào khác cho nó hoặc giữ một tham chiếu đến nó. Tôi asked the V8 guys about it (V8 là công cụ JavaScript trong Chrome) và họ nói rằng Chrome sẽ "... trong hầu hết các trường hợp ..." sử dụng lại chức năng triển khai chức năng cơ bản cho các đối tượng chức năng khác nhau được tạo tại cùng một điểm trong mã nguồn và họ sẽ "mong đợi" rằng hầu hết các động cơ khác sẽ làm như vậy.

Vì vậy, JSHint có thể là một chút over-the-top trong trường hợp cụ thể này. Nhưng nó thường là một cảnh báo hữu ích, đặc biệt nếu các hàm bạn đang tạo bên trong vòng lặp tham chiếu đến các biến có nội dung thay đổi trong vòng lặp, đó là lỗi đóng cửa cổ điển mà mọi người thực hiện.

Nhưng về cơ bản hơn, person là một String (đó là tên của một tài sản trong people), và String không có forEach. Bạn muốn:

for (var person in people) { 
    people[person].forEach(handlePerson); 
} 
function handlePerson(item) { 
    console.log(item) 
} 

... ví dụ: people[person] để lấy mảng cho khóa đó.

+1

Tôi đoán anh ấy có nghĩa là 'người [người] .forEach (...) '. Dù sao, cảnh báo đó dường như khá ngu ngốc với các công cụ JS hiện đại - chúng có nhiều khả năng sẽ không tạo ra một chức năng mới cho mỗi lần lặp lại. – ThiefMaster

+0

Ít nhất V8 không: http://stackoverflow.com/questions/10160275/v8-internals-handling-of-anonymous-functions – ThiefMaster

+0

'người' là một đối tượng (chứa mảng). –

1

Bạn được phép sử dụng forEach bên trong vòng lặp, nhưng bạn không được phép khai báo hàm bên trong vòng lặp.

function looper (item) { 
    console.log(item) 
} 

for (var person in people) { 
    person.forEach(looper) 
} 

... nếu không bạn đang tạo lại cùng chức năng cho mỗi lần lặp lại.

0

Nó không phải là forEach, đó là chức năng ẩn danh mà nó đang phàn nàn.

0

Lý do đây là vấn đề là nó tạo một tham chiếu đối tượng mới cho hàm ẩn danh trong cuộc gọi foreach trong Heap mỗi lần bạn thực hiện việc này.Sẽ tốt hơn nếu bạn gán chức năng cho một biến ngoài vòng lặp, theo cách đó bạn không ăn bộ nhớ một cách không cần thiết

7

Ngoài những người bình luận khác, nếu bạn biết mình đang làm gì, bạn có thể tắt cảnh báo với JSHint tùy chọn loopfunc:

/*jshint loopfunc:true */ 

for (var person in people) { 
    person.forEach(function(item) { 
    console.log(item) 
    }) 
} 

bạn có thể thiết lập tùy chọn JSHint toàn cầu (nếu bạn đang sử dụng mô-đun NPM), mỗi tập tin hoặc mỗi chức năng.

+0

Đọc bài này vào năm 2016: Tôi đã làm rất nhiều ** không ** biết tôi đang làm gì. PS. Xin chào Anton! – mikemaccana

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