Hướng dẫn reference type and losing this in javascript - loại tham chiếu và mất cái này trong javascript

Tính năng ngôn ngữ chuyên sâu

Bài viết này bao gồm một chủ đề nâng cao, để hiểu một số trường hợp cạnh nhất định tốt hơn.

Điều đó không quan trọng. Nhiều nhà phát triển có kinh nghiệm sống tốt mà không biết nó. Đọc tiếp nếu bạn muốn biết mọi thứ hoạt động như thế nào dưới mui xe.

Một cuộc gọi phương thức được đánh giá động có thể mất

(user.name == "John" ? user.hi : user.bye)(); // Error!
0.

Ví dụ:

let user = {
  name: "John",
  hi() { alert(this.name); },
  bye() { alert("Bye"); }
};

user.hi(); // works

// now let's call user.hi or user.bye depending on the name
(user.name == "John" ? user.hi : user.bye)(); // Error!

Trên dòng cuối cùng có một toán tử có điều kiện chọn

(user.name == "John" ? user.hi : user.bye)(); // Error!
1 hoặc
(user.name == "John" ? user.hi : user.bye)(); // Error!
2. Trong trường hợp này, kết quả là
(user.name == "John" ? user.hi : user.bye)(); // Error!
1.

Sau đó, phương thức được gọi ngay lập tức với dấu ngoặc đơn

(user.name == "John" ? user.hi : user.bye)(); // Error!
4. Nhưng nó không hoạt động chính xác!

Như bạn có thể thấy, cuộc gọi dẫn đến một lỗi, bởi vì giá trị của

(user.name == "John" ? user.hi : user.bye)(); // Error!
5 bên trong cuộc gọi trở thành
(user.name == "John" ? user.hi : user.bye)(); // Error!
6.

Điều này hoạt động (Phương thức chấm đối tượng):

Điều này không (phương pháp đánh giá):

(user.name == "John" ? user.hi : user.bye)(); // Error!

Tại sao? Nếu chúng ta muốn hiểu lý do tại sao nó xảy ra, hãy để Lôi nhận được dưới mui xe của cách thức hoạt động của

(user.name == "John" ? user.hi : user.bye)(); // Error!
7.

Loại tham chiếu giải thích

Nhìn kỹ, chúng tôi có thể nhận thấy hai hoạt động trong tuyên bố

(user.name == "John" ? user.hi : user.bye)(); // Error!
7:

  1. Đầu tiên, dấu chấm
    (user.name == "John" ? user.hi : user.bye)(); // Error!
    9 lấy tài sản
    let user = {
      name: "John",
      hi() { alert(this.name); }
    };
    
    // split getting and calling the method in two lines
    let hi = user.hi;
    hi(); // Error, because this is undefined
    0.
  2. Sau đó dấu ngoặc đơn
    (user.name == "John" ? user.hi : user.bye)(); // Error!
    4 thực hiện nó.

Vì vậy, làm thế nào để thông tin về

(user.name == "John" ? user.hi : user.bye)(); // Error!
0 được chuyển từ phần đầu tiên sang phần thứ hai?

Nếu chúng ta đặt các hoạt động này trên các dòng riêng biệt, thì chắc chắn

(user.name == "John" ? user.hi : user.bye)(); // Error!
0 sẽ bị mất:

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined

Ở đây

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
4 đặt hàm vào biến, và sau đó trên dòng cuối cùng, nó hoàn toàn độc lập, và do đó, không có
(user.name == "John" ? user.hi : user.bye)(); // Error!
0.

Để thực hiện các cuộc gọi

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
6 hoạt động, JavaScript sử dụng một thủ thuật - dấu chấm
(user.name == "John" ? user.hi : user.bye)(); // Error!
9 trả về không phải là một hàm, mà là một giá trị của loại tham chiếu đặc biệt.

Loại tham chiếu là một loại đặc điểm kỹ thuật của người Viking. Chúng ta có thể sử dụng rõ ràng nó, nhưng nó được sử dụng trong nội bộ bởi ngôn ngữ.

Giá trị của loại tham chiếu là sự kết hợp ba giá trị

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
8, trong đó:

  • let user = {
      name: "John",
      hi() { alert(this.name); }
    };
    
    // split getting and calling the method in two lines
    let hi = user.hi;
    hi(); // Error, because this is undefined
    9 là đối tượng.
  • // Reference Type value
    (user, "hi", true)
    0 là tên tài sản.
  • // Reference Type value
    (user, "hi", true)
    1 là đúng nếu
    // Reference Type value
    (user, "hi", true)
    2 có hiệu lực.

Kết quả của quyền truy cập thuộc tính

(user.name == "John" ? user.hi : user.bye)(); // Error!
1 không phải là một hàm, mà là một giá trị của loại tham chiếu. Đối với
(user.name == "John" ? user.hi : user.bye)(); // Error!
1 ở chế độ nghiêm ngặt, đó là:

// Reference Type value
(user, "hi", true)

Khi dấu ngoặc đơn

(user.name == "John" ? user.hi : user.bye)(); // Error!
4 được gọi trên loại tham chiếu, họ sẽ nhận được thông tin đầy đủ về đối tượng và phương thức của nó và có thể đặt đúng ____10 (
// Reference Type value
(user, "hi", true)
7 trong trường hợp này).

Loại tham chiếu là một loại nội bộ trung gian đặc biệt của người Viking, với mục đích chuyển thông tin từ DOT

// Reference Type value
(user, "hi", true)
8 sang gọi dấu ngoặc đơn
(user.name == "John" ? user.hi : user.bye)(); // Error!
4.

Bất kỳ hoạt động nào khác như gán

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
4 đều loại bỏ loại tham chiếu nói chung, lấy giá trị của
(user.name == "John" ? user.hi : user.bye)(); // Error!
1 (một hàm) và truyền nó. Vì vậy, bất kỳ hoạt động nào khác có thể mất các hoạt động khác.

Vì vậy, kết quả là, giá trị của

(user.name == "John" ? user.hi : user.bye)(); // Error!
0 chỉ được truyền đúng cách nếu hàm được gọi trực tiếp bằng cách sử dụng dấu chấm chấm
(user.name == "John" ? user.hi : user.bye)(); // Error!
7 hoặc vuông
let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)()
5 (chúng làm tương tự ở đây). Có nhiều cách khác nhau để giải quyết vấn đề này như func.bind ().

Bản tóm tắt

Loại tham chiếu là một loại ngôn ngữ nội bộ.

Đọc một thuộc tính, chẳng hạn như với DOT

// Reference Type value
(user, "hi", true)
8 trong
(user.name == "John" ? user.hi : user.bye)(); // Error!
7 trả về không chính xác giá trị thuộc tính, mà là một giá trị loại tham chiếu đặc biệt của người dùng lưu trữ cả giá trị thuộc tính và đối tượng được lấy từ.

Đó là cách mà phương thức tiếp theo gọi

(user.name == "John" ? user.hi : user.bye)(); // Error!
4 để lấy đối tượng và đặt
(user.name == "John" ? user.hi : user.bye)(); // Error!
0 cho nó.

Đối với tất cả các hoạt động khác, loại tham chiếu sẽ tự động trở thành giá trị thuộc tính (một hàm trong trường hợp của chúng tôi).

Toàn bộ cơ học được ẩn khỏi mắt chúng ta. Nó chỉ quan trọng trong các trường hợp tinh tế, chẳng hạn như khi một phương thức thu được động từ đối tượng, sử dụng một biểu thức.

Nhiệm vụ

Tầm quan trọng: 2

Kết quả của mã này là gì?

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)()

P.S. Có một cạm bẫy :)

Error!!

Thử nó:

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!

Thông báo lỗi trong hầu hết các trình duyệt không cho chúng ta nhiều manh mối về những gì đã sai.

Lỗi xuất hiện do dấu chấm phẩy bị thiếu sau

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
0.

JavaScript không tự động chèn một dấu chấm phẩy trước khung

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
1, vì vậy nó đọc mã như:

let user = { go:... }(user.go)()

Sau đó, chúng ta cũng có thể thấy rằng một biểu thức chung như vậy là một cách cú pháp của đối tượng

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
2 như là một hàm với đối số
let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
3. Và điều đó cũng xảy ra trên cùng một dòng với
let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
4, vì vậy đối tượng
// Reference Type value
(user, "hi", true)
7 chưa được xác định, do đó lỗi.

Nếu chúng ta chèn dấu chấm phẩy, tất cả đều ổn:

let user = {
  name: "John",
  go: function() { alert(this.name) }
};

(user.go)() // John

Xin lưu ý rằng dấu ngoặc đơn xung quanh

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
3 không làm gì ở đây. Thông thường, họ thiết lập thứ tự hoạt động, nhưng ở đây, DOT
// Reference Type value
(user, "hi", true)
8 hoạt động trước tiên, vì vậy, không có hiệu quả. Chỉ có những điều bán kết quan trọng.

Tầm quan trọng: 3

Trong mã bên dưới, chúng tôi dự định gọi phương thức

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
8 4 lần liên tiếp.

Nhưng gọi

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!
9 và
let user = { go:... }(user.go)()
0 hoạt động khác với
let user = { go:... }(user.go)()
1 và
let user = { go:... }(user.go)()
2. Tại sao?

let obj, method;

obj = {
  go: function() { alert(this); }
};

obj.go();               // (1) [object Object]

(obj.go)();             // (2) [object Object]

(method = obj.go)();    // (3) undefined

(obj.go || obj.stop)(); // (4) undefined

Ở đây, những lời giải thích.

  1. Đó là một cuộc gọi phương thức đối tượng thông thường.

  2. Điều tương tự, dấu ngoặc đơn không thay đổi thứ tự hoạt động ở đây, DOT dù sao là trước tiên.

  3. Ở đây chúng tôi có một cuộc gọi phức tạp hơn

    let user = { go:... }(user.go)()
    3. Cuộc gọi hoạt động như thể nó được chia thành hai dòng:

    f = obj.go; // calculate the expression
    f();        // call what we have

    Ở đây

    let user = { go:... }(user.go)()
    4 được thực thi như một hàm, không có
    (user.name == "John" ? user.hi : user.bye)(); // Error!
    0.

  4. Điều tương tự như

    let user = { go:... }(user.go)()
    1, ở bên trái của dấu ngoặc đơn
    (user.name == "John" ? user.hi : user.bye)(); // Error!
    4 chúng ta có một biểu thức.

Để giải thích hành vi của

let user = { go:... }(user.go)()
1 và
let user = { go:... }(user.go)()
2, chúng ta cần nhớ lại rằng người truy cập tài sản (dấu chấm hoặc dấu ngoặc vuông) trả về giá trị của loại tham chiếu.

Bất kỳ hoạt động nào trên đó ngoại trừ một cuộc gọi phương thức (như gán

let user = {
  name: "John",
  go: function() { alert(this.name) }
};

(user.go)() // John
0 hoặc
let user = {
  name: "John",
  go: function() { alert(this.name) }
};

(user.go)() // John
1) biến nó thành một giá trị thông thường, không mang thông tin cho phép đặt ____10.

Loại tham chiếu trong JavaScript là gì?

Các loại dữ liệu tham chiếu, không giống như các loại dữ liệu nguyên thủy, có bản chất động. Đó là, họ không có kích thước cố định. Hầu hết chúng được coi là đối tượng, và do đó có các phương pháp. Ví dụ về các loại dữ liệu đó bao gồm mảng, chức năng, bộ sưu tập và tất cả các loại đối tượng khác.dynamic in nature. That is, they do not have a fixed size. Most of them are considered as objects, and therefore have methods. Examples of such data types include arrays, functions, collections, and all other types of objects.

Sự khác biệt giữa loại giá trị và loại tham chiếu trong JavaScript là gì?

Trong JavaScript, bạn có thể chuyển qua giá trị và bằng cách tham khảo.Sự khác biệt chính giữa hai là chuyển qua giá trị xảy ra khi gán nguyên thủy trong khi truyền bằng cách tham chiếu khi gán các đối tượng.passing by value happens when assigning primitives while passing by reference when assigning objects.

JavaScript có thể sao chép đối tượng bằng tài liệu tham khảo không?

Các đối tượng được gán và sao chép bằng tham chiếu.Nói cách khác, một thay đổi lưu trữ không phải là giá trị đối tượng của người dùng, mà là một tham chiếu trên mạng (địa chỉ trong bộ nhớ) cho giá trị.Vì vậy, sao chép một biến như vậy hoặc truyền nó như một đối số chức năng sao chép tham chiếu đó, không phải chính đối tượng.. In other words, a variable stores not the “object value”, but a “reference” (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself.

Giá trị loại tham chiếu nào được JavaScript chấp nhận?

JavaScript có 5 loại dữ liệu được truyền theo giá trị: boolean, null, không xác định, chuỗi và số.Chúng tôi sẽ gọi các loại nguyên thủy này.JavaScript có 3 loại dữ liệu được truyền bởi tham chiếu: mảng, chức năng và đối tượng.Array , Function , and Object .