Mọi người có thể giải thích ngữ cảnh để sử dụng các phương thức call
và apply
trong Javascript không?ngữ cảnh để sử dụng cuộc gọi và áp dụng trong Javascript?
Tại sao sử dụng call
và apply
thay vì gọi trực tiếp một chức năng?
Mọi người có thể giải thích ngữ cảnh để sử dụng các phương thức call
và apply
trong Javascript không?ngữ cảnh để sử dụng cuộc gọi và áp dụng trong Javascript?
Tại sao sử dụng call
và apply
thay vì gọi trực tiếp một chức năng?
Chỉ khi bạn sử dụng call
hoặc apply
bạn có thể sửa đổi ngữ cảnh this
bên trong hàm.
Không giống như các ngôn ngữ khác - trong JavaScript this
không đề cập đến đối tượng hiện tại - thay vì ngữ cảnh thực thi và có thể được đặt bởi người gọi.
Nếu bạn gọi một chức năng bằng cách sử dụng từ khóa new
this
một cách chính xác sẽ giới thiệu đến các đối tượng mới (bên trong hàm constructor) ..
Nhưng trong mọi trường hợp khác - this
sẽ đề cập đến đối tượng toàn cầu trừ khi thiết lập một cách rõ ràng thông qua hãy gọi
Nó có thể ám chỉ đến obj người gọi, nếu sử dụng cú pháp 'obj.whatever();'. –
Câu lệnh "Nhưng trong tất cả các trường hợp khác - điều này sẽ ám chỉ đối tượng toàn cục trừ khi được thiết lập rõ ràng thông qua cuộc gọi" cần được sửa thành sau: "Nhưng trong tất cả các trường hợp khác, trừ khi đặt rõ ràng thông qua cuộc gọi, điều này sẽ ám chỉ đối tượng chung sử dụng Ecmascript 3 hoặc Ecmascript 5 (hoặc mới hơn) ở chế độ không nghiêm ngặt.Tuy nhiên, trong Ecmascript 5 (hoặc mới hơn) với chế độ nghiêm ngặt, điều này luôn luôn không xác định nếu không được đặt rõ ràng và JS Engine sẽ ném một ngoại lệ khi bạn truy cập. " Tham khảo: http://stackoverflow.com/questions/9822561/why-is-this-in-an-anonymous-function-undefined-when-using-strict –
Bạn sử dụng call
hoặc apply
khi bạn muốn chuyển giá trị this
khác nhau cho hàm. Về bản chất, điều này có nghĩa là bạn muốn thực hiện một hàm như thể nó là một phương thức của một đối tượng cụ thể. Sự khác biệt duy nhất giữa hai là call
hy vọng các tham số được phân tách bằng dấu phẩy, trong khi apply
mong đợi các tham số trong một mảng.
Một ví dụ từ Mozilla's apply
page, nơi nhà xây dựng đang bị xiềng xích:
function Product(name, price) {
this.name = name;
this.price = price;
if (price < 0)
throw RangeError('Cannot create product "' + name + '" with a negative price');
return this;
}
function Food(name, price) {
Product.apply(this, arguments);
this.category = 'food';
}
Food.prototype = new Product();
function Toy(name, price) {
Product.apply(this, arguments);
this.category = 'toy';
}
Toy.prototype = new Product();
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
gì Product.apply(this, arguments)
làm như sau: Các nhà xây dựng Product
được áp dụng như một chức năng trong mỗi Food
và Toy
nhà thầu, và mỗi một trong các đối tượng các phiên bản đang được chuyển thành this
. Do đó, mỗi Food
và Toy
hiện có các thuộc tính this.name
và this.category
.
chỉ là một câu hỏi về đoạn mã được cung cấp, tại sao Toy and Food's nguyên mẫu được thay thế bởi một đối tượng sản phẩm? – davids
Nhận xét chỉ để bump @davids câu hỏi: tại sao chúng ta cần phải làm 'Toy.prototype = new Product();'? Tôi đã thử nghiệm điều này và loại bỏ những dòng này dường như không có sự khác biệt trong kết quả cuối cùng. – adrianp
@davids & @adrianp: Cần thiết để làm cho Đồ ăn và Đồ chơi kế thừa từ Sản phẩm. Hãy xem ví dụ này: http://jsfiddle.net/Shawn/xNEYf/ Tôi đã xóa 'Toy.prototype = new Product();' nhưng còn lại 'Food.prototype = new Product();' trong, vì vậy bây giờ thực phẩm thừa hưởng từ Sản phẩm, nhưng Toy thì không. Tôi cũng đã thêm một phương thức vào nguyên mẫu của Product và gọi nó là từ Food and Toy để làm cho việc thừa kế thiếu rõ ràng hơn (chỉ cần mở console và chạy mã, Food có thể gọi phương thức được thừa kế từ Product, nhưng Toy không thể và ném lỗi) . – Shawn
Nếu bạn có kinh nghiệm với jQuery, bạn sẽ biết rằng hầu hết các chức năng đều sử dụng đối tượng this
. Ví dụ: collection.each(function() { ... });
Bên trong hàm này, "this"
đề cập đến đối tượng trình lặp. Đây là một cách sử dụng có thể.
Cá nhân tôi đã sử dụng .apply()
để triển khai hàng đợi yêu cầu - tôi đẩy một loạt đối số vào hàng đợi và khi đến lúc thực thi nó, tôi lấy một phần tử và chuyển nó làm đối số cho hàm xử lý sử dụng .apply()
, do đó làm cho mã sạch hơn sau đó nếu phải vượt qua một mảng đối số như một đối số đầu tiên. Đó là một ví dụ khác.
Nói chung, xin lưu ý rằng những cách gọi hàm này tồn tại và bạn có thể thấy một ngày nào đó thuận tiện để sử dụng để triển khai chương trình của mình.
Bạn sử dụng .call()
khi bạn muốn làm cho hàm thực thi với giá trị this
khác. Nó đặt giá trị this
như được chỉ định, đặt các đối số như được chỉ định và sau đó gọi hàm. Sự khác biệt giữa .call()
và chỉ thực thi hàm là giá trị của con trỏ this
khi hàm thực thi.Khi bạn thực thi hàm bình thường, javascript sẽ quyết định con trỏ this
sẽ là gì (thường là ngữ cảnh chung window
trừ khi hàm được gọi là phương thức trên đối tượng). Khi bạn sử dụng .call()
, bạn chỉ định chính xác những gì bạn muốn this
được đặt thành.
Bạn sử dụng .apply()
khi đối số bạn muốn chuyển đến hàm nằm trong một mảng. .apply()
cũng có thể khiến chức năng thực thi với giá trị this
cụ thể. .apply()
thường được sử dụng nhất khi bạn có số đối số không xác định đến từ một số nguồn khác. Nó thường được sử dụng quá vượt qua các đối số từ một cuộc gọi chức năng khác bằng cách sử dụng biến cục bộ đặc biệt arguments
, trong đó có một mảng đối số được chuyển đến hàm hiện tại của bạn.
Tôi tìm thấy trang tham chiếu MDN cho .call() và .apply() hữu ích.
Cảm ơn bạn, bạn giải thích nó rất tốt. Cuối cùng hiểu cách sử dụng đối số đầu tiên. –
Tôi không thể nghĩ ra bất kỳ tình huống bình thường nào khi đặt thisArg thành thứ gì đó khác nhau là mục đích sử dụng.
Mục đích của việc áp dụng là chuyển một mảng giá trị cho một hàm muốn các giá trị đó làm đối số.
Nó đã được thay thế trong tất cả việc sử dụng hàng ngày thông thường của nhà điều hành dàn trải.
ví dụ:
// Finding the largest number in an array
`Math.max.apply(null, arr)` becomes `Math.max(...arr)`
// Inserting the values of one array at the start of another
Array.prototype.unshift.apply(arr1, arr2);
// which becomes
arr1 = [...arr2, ...arr1]
Nếu bạn có kinh nghiệm với Object Oriented Programming
sau đó gọi và áp dụng sẽ có ý nghĩa nếu bạn so sánh nó với thừa kế và ghi đè các thuộc tính hay phương thức/chức năng của lớp cha mẹ từ lớp trẻ. Điều này tương tự với lệnh gọi javascript như sau:
function foo() {
this.helloworld = "hello from foo"
}
foo.prototype.print = function() {
console.log(this.helloworld)
}
foo.prototype.main = function() {
this.print()
}
function bar() {
this.helloworld = 'hello from bar'
}
// declaring print function to override the previous print
bar.prototype.print = function() {
console.log(this.helloworld)
}
var iamfoo = new foo()
iamfoo.main() // prints: hello from foo
iamfoo.main.call(new bar()) // override print and prints: hello from bar
[Đọc này] (https://t.co/BVQPwfqqnO) đã giúp tôi hiểu điểm 'thisArg' khi gọi 'apply()' và 'call() 'mà dường như là cốt lõi của câu hỏi của bạn. Bạn cần hiểu nguyên hàm invocation trong Javascript –