Hướng dẫn why this keyword is undefined in javascript? - tại sao từ khóa này không được xác định trong javascript?

Tôi đang thử xây dựng chức năng trình chiếu với cách nghĩa đen của OOP.

Vì vậy, đây là mã của tôi:

"use strict";

var slideshow = {

    elSet   : $(".slideshow"),
    elCount : indexCount(".dealList"),
    elWidth : width(".dealList"),
    elNo    : 1,
    next    : function() {

                if (this.elNo < this.elCount) {
                    console.log(this.elSet);
                    this.elNo += 1;
                    this.elSet.style.transform = "translateX(-" + this.elWidth * this.elNo + "px)";
                }
                else {
                    console.log(this.elSet);
                    this.elNo = 1;
                    this.elSet.style.transform = "translateX(-" + this.elWidth * this.elNo + "px)";
                }
    },
    initial : function() {

                var loop = setInterval(this.next, 5000);
    }

}

slideshow.initial();

Sự cố xảy ra trong bảng điều khiển trình duyệt:

  1. không có bộ nhớ
  2. Console.log Trả về không xác định

Có thể vấn đề xảy ra vì từ khóa này?

Có gì sai với mã của tôi?

2 phút đọc

Khi một hàm đã được sử dụng như một hàm bậc cao (được thông qua như một đối số), chúng sẽ mất nhận thức về this, ngay cả khi chúng ở cùng một đối tượng. Ví dụ:

    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'

Một cách nhanh chóng để giải quyết vấn đề này là bằng cách chuyển chức năng bị ràng buộc đến đối tượng. Ví dụ.:

    > p.sayHi(p.getName.bind(p));

    'Hi Jon'

Nhưng liệu có phải là tuyệt vời để hiểu nguồn gốc của vấn đề này không?

Một vấn đề của bối cảnh

Tại sao điều này xảy ra? Chà, trong JavaScript khi bạn gán hàm của một đối tượng cho một biến/tham số, bạn thực sự đang tách phương thức đó khỏi đối tượng của nó:

> const myFunc = instanz.myFunction;
// or 
> function myFunc2(f) {
    f();
 }

Trong trường hợp như vậy, bên trong myFunction giá trị của this không giống như

    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
1 nữa, nhưng nó sẽ nhận được giá trị của this từ bối cảnh toàn cầu, trong chế độ nghiêm ngặt là
    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
3 thay vì đối tượng toàn cầu
    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
4.

Chà, lúc đầu trông không rõ ràng, nhưng với một ví dụ ngắn, nó sẽ dễ hiểu hơn.

Một ví dụ để kiểm tra lý thuyết

  1. Hãy để tạo ra một lớp kiểm tra nhận thức được bối cảnh của nó

     > function Soldier(numBullets) {
         this.numBullets = numBullets;
    
         this.checkStatus = function() {
             "use strict";
             console.log(this === captain);
             console.log(`I am ${this}`);
             console.log(`I have ${this.numBullets} bullets`);
         }
      }
    

  2. Tạo một thể hiện

        > function Person(name, gender) {
            this.name = name;
    
            this.sayHi = function (descriptor) {
                return `Hi ${descriptor()}`;
            }
    
            this.getName = function() {
                return this.name;
            }
         }
    
        > p = new Person("Jon");
        > p.sayHi(p.getName);
    
        'Hi undefined'
    
    5 để xem liệu nó có hoạt động như mong đợi không

     > captain = new Soldier(5);
     > captain.checkStatus();
    
     true
     I am [object Object]
     I have 5 bullets
    

  3. Hãy để xem những gì xảy ra nếu chúng ta tách chức năng

        > function Person(name, gender) {
            this.name = name;
    
            this.sayHi = function (descriptor) {
                return `Hi ${descriptor()}`;
            }
    
            this.getName = function() {
                return this.name;
            }
         }
    
        > p = new Person("Jon");
        > p.sayHi(p.getName);
    
        'Hi undefined'
    
    6 khỏi đối tượng của nó
        > function Person(name, gender) {
            this.name = name;
    
            this.sayHi = function (descriptor) {
                return `Hi ${descriptor()}`;
            }
    
            this.getName = function() {
                return this.name;
            }
         }
    
        > p = new Person("Jon");
        > p.sayHi(p.getName);
    
        'Hi undefined'
    
    5:

     > captainStatus = captain.checkStatus;
     > captainStatus();
        
     false
     I am undefined
     Uncaught TypeError: Cannot read property 'numBullets' of undefined
    

Điều này xác nhận rằng

    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
6 được tách ra khỏi
    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
5 và this
    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
3.

Điều này xảy ra mỗi lần hoặc chỉ khi nó ở

    > p.sayHi(p.getName.bind(p));

    'Hi Jon'
2? Nếu chỉ thị
    > p.sayHi(p.getName.bind(p));

    'Hi Jon'
2 bị xóa và bạn lại tách chức năng khỏi đối tượng của nó, thì việc chạy nó trong trình duyệt của bạn sẽ lấy đối tượng toàn cầu
    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
4:

> function Soldier(numBullets) {
    this.numBullets = numBullets;

    this.checkStatus = function() {
        console.log(this === captain);
        console.log(`I am ${this}`);
        console.log(`I have ${this.numBullets} bullets`);
    }
  }
> captain = new Soldier(5);
> captainStatus = captain.checkStatus;
> captainStatus(); 

false
I am [object Window]
I have undefined bullets

Điều này đã xảy ra bởi vì trong trình duyệt

    > function Person(name, gender) {
        this.name = name;

        this.sayHi = function (descriptor) {
            return `Hi ${descriptor()}`;
        }

        this.getName = function() {
            return this.name;
        }
     }

    > p = new Person("Jon");
    > p.sayHi(p.getName);

    'Hi undefined'
4 là đối tượng sở hữu
    > p.sayHi(p.getName.bind(p));

    'Hi Jon'
6 tại thời điểm thực hiện nó. Hãy thử lại các hướng dẫn tương tự, nhưng lần này trong bảng điều khiển NodeJS để xem điều gì sẽ xảy ra. Ai là chủ sở hữu của phương pháp lần này?

Kết luận

Mỗi lần chúng tôi sẽ thực thi các chức năng trong JavaScript, điều quan trọng là phải nhớ rằng:

  • Một phương pháp có thể được tách ra khỏi một đối tượng thành một biến riêng biệt, ví dụ:
        > p.sayHi(p.getName.bind(p));
    
        'Hi Jon'
    
    7.
  • Cách chúng tôi gọi một hàm thay đổi bối cảnh mà nó được thực thi.
  • Trong quá trình gọi chức năng, tức là việc mời một hàm không được gắn vào một đối tượng, this sẽ được tìm kiếm trong bối cảnh toàn cầu.
  • Từ khóa this
        > function Person(name, gender) {
            this.name = name;
    
            this.sayHi = function (descriptor) {
                return `Hi ${descriptor()}`;
            }
    
            this.getName = function() {
                return this.name;
            }
         }
    
        > p = new Person("Jon");
        > p.sayHi(p.getName);
    
        'Hi undefined'
    
    3 trong một lời mời chức năng ở chế độ nghiêm ngặt.

Nó thậm chí còn thú vị hơn khi bạn biết rằng khi sử dụng các hàm mũi tên trong các kịch bản này, bạn thực sự có được bối cảnh tĩnh trên các loại mời khác nhau.

Xem thêm

  • Giải thích nhẹ nhàng về ‘Điều này trong JavaScript
  • Tài liệu chính thức của Mozilla về nhà điều hành ’này

Làm cách nào để dừng không xác định trong JavaScript?

Nhưng điều đó không phải lúc nào cũng có thể ...
Mẹo 1: Ưu tiên const, nếu không hãy sử dụng, nhưng hãy nói lời tạm biệt với var ..
Mẹo 2: Tăng sự gắn kết ..
Mẹo 3: Kiểm tra sự tồn tại của tài sản ..
Mẹo 4: Phá hủy các thuộc tính đối tượng truy cập ..
Mẹo 5: Điền vào đối tượng với các thuộc tính mặc định ..
Tiền thưởng: Nullish Coalescing ..
Mẹo 6: Sử dụng giá trị tham số mặc định ..

Tại sao điều này không được xác định trong chế độ nghiêm ngặt?

Trong chế độ nghiêm ngặt, bây giờ nó không được xác định.Khi một hàm được gọi với cuộc gọi hoặc áp dụng, nếu giá trị là giá trị nguyên thủy, thì cái này đã được đóng hộp vào một đối tượng (hoặc đối tượng toàn cầu cho không xác định và null).Trong chế độ nghiêm ngặt, giá trị được truyền trực tiếp mà không cần chuyển đổi hoặc thay thế.When a function was called with call or apply , if the value was a primitive value, this one was boxed into an object (or the global object for undefined and null ). In strict mode, the value is passed directly without conversion or replacement.

Tại sao từ khóa này được sử dụng trong JavaScript?

Từ khóa này đề cập đến một đối tượng đang thực thi đoạn mã hiện tại.Nó tham chiếu đối tượng đang thực thi chức năng hiện tại.Nếu chức năng được tham chiếu là một hàm thông thường, thì điều này tham khảo đối tượng toàn cầu.refers to an object that is executing the current piece of code. It references the object that is executing the current function. If the function being referenced is a regular function, “this” references the global object.

Những gì được xác định và không xác định trong JavaScript?

Tóm lại, "không xác định" và "không được xác định" là hai giá trị khác nhau trong JavaScript."Không xác định" chỉ ra rằng một biến đã được khai báo nhưng không được đưa ra một giá trị, trong khi "không xác định" chỉ ra rằng một biến không tồn tại."undefined" indicates that a variable has been declared but not given a value, while "not defined" indicates that a variable does not exist.