2014-12-11 21 views
7

Nếu một biến không có sẵn trong một hàm khi cần, thì nó sẽ được tìm kiếm trong chuỗi phạm vi (đóng cửa), nhưng lần khác đang được tìm kiếm trong chuỗi nguyên mẫu. Tôi đang cố gắng quấn quanh đầu tôi đang xảy ra khi nào. Tôi đã tự hỏi nếu có ai đó có thể vui lòng xóa sương mù cho tôi, hoặc giới thiệu cho tôi một số tài liệu thảo luận về chủ đề này một cách cụ thể.Tra cứu chuỗi phạm vi và xem xét nguyên mẫu - Đó là khi

Ví dụ, tôi có thể nói đúng: - Các đối tượng và do đó các biến công khai gắn với ngữ cảnh (điều này) luôn được tra cứu trong chuỗi nguyên mẫu? - Biến riêng tư luôn được tra cứu trong chuỗi phạm vi (tức là chuỗi chức năng trong ngữ cảnh thực thi)? - Có trường hợp nào khi chương trình đang tìm kiếm cả hai?

Tôi đã thử nghiệm ba trường hợp khác nhau (tìm kiếm chuỗi phạm vi, tra cứu mẫu và không tra cứu), nhưng rất tiếc Nó không giúp đủ để tìm hiểu điều này.

var Food = function(){ 
    var t = 1; // for closure 

    this.timeToPrepare = function(){ // Scope chain lookup 
     console.log(t * 3); 
    }; 

    this.timeToMake = function(){ // This is looked up in the prototype chain 
     console.log(this.t * 3); 
    }; 

    this.timeToEat = function(t){ //No lookup 
     console.log(t * 3); 
    }; 

    }; 

    Food.prototype.t = 2; 

    (function(){ 
    var pizza = new Food; 
    pizza.timeToPrepare(); //3 
    pizza.timeToMake();  //6 
    pizza.timeToEat(3);  //9 
    })(); 

enter image description here

Cảm ơn!

+1

Các chuỗi nguyên mẫu sẽ chỉ được tra cứu khi bạn truy cập một giá trị thuộc tính trên một đối tượng bằng cách sử dụng toán tử dấu chấm hoặc dấu ngoặc vuông (đối tượng có thể được tham chiếu bởi biến hoặc ngữ cảnh hiện tại 'this'). Nếu bạn tham chiếu một biến bằng mã định danh của nó, nó sẽ được tra cứu bắt đầu với phạm vi của hàm hiện tại, và sau đó làm việc đến các mức đóng cao hơn. Đây là lý do tại sao khi bạn định nghĩa một đối số được gọi là 't' cho một hàm, nó sẽ đổ bóng bất kỳ biến đóng nào được gọi là' t'. Điều tương tự nếu bạn khai báo một 'var t' trong một hàm. Không chính xác chắc chắn nếu điều này trả lời tất cả các câu hỏi của bạn. – sbking

+1

Vì vậy, nói cách khác, tra cứu mẫu và tra cứu biến là hoàn toàn riêng biệt trong JavaScript. Nếu bạn tham chiếu một giá trị trực tiếp bởi một biến chứ không phải là một thuộc tính trên một đối tượng, JavaScript không có bất kỳ đối tượng nào trên chuỗi nguyên mẫu của nó để thực hiện tra cứu. – sbking

+0

Cảm ơn đây chính là điều tôi đang nhận được! i) Có phải chuỗi tìm kiếm chuỗi phạm vi EITHER luôn luôn tra cứu hay không, nhưng không phải là cả hai? ii.) Nếu "bạn truy cập một giá trị tài sản trên một đối tượng bằng cách sử dụng toán tử dấu chấm hoặc dấu ngoặc vuông", có nghĩa là nó sẽ luôn được tra cứu trong chuỗi nguyên mẫu chứ không phải chuỗi phạm vi? - Nếu "bạn tham chiếu biến bằng mã định danh của nó" có nghĩa là nó luôn luôn được tìm kiếm trong chuỗi phạm vi? – Crocodile

Trả lời

14

Biến số được tìm kiếm trên chuỗi phạm vi, bắt đầu với ngữ cảnh thực thi hiện tại và đi lên cây có ngữ cảnh thực thi kèm theo.

Thuộc tính đang nhìn lên trước hết trên các đối tượng cơ sở, sau đó trên [[Prototoype]] chuỗi của đối tượng đó (ví dụ: nguyên mẫu nội bộ của mình).

Vì vậy, nếu bạn làm:

foo 

foo sẽ được coi như là một biến và nhìn lên trên chuỗi phạm vi. Tên biến không bao giờ đủ điều kiện, bạn không thể hướng chúng đến một bối cảnh thực thi cụ thể để được tra cứu. Nếu có hai biến trên chuỗi phạm vi có cùng tên, bạn chỉ có thể truy cập vào tên được gặp lần đầu khi đi cùng chuỗi (có một cách xung quanh điều này đặc biệt cho các biến toàn cầu), ví dụ

var a = 'global a'; 

function foo() { 
    var a = 'local a'; 
    return a; 
} 

console.log(foo()); // local a 

Ở phía trên, một trong chức năng giải quyết vào biến địa phương một. Trong trường hợp các biến toàn cục, chúng được tạo các thuộc tính của đối tượng chung để bạn có thể truy cập chúng ngay cả khi chúng bị "ẩn" bởi cùng một thuộc tính cục bộ có tên, ví dụ:

function foo() { 
    var = 'local a'; 
    // this will reference the global object 
    return this.a; 
} 

console.log(foo()); // global a 

Ngược lại, tên thuộc tính luôn luôn đi trước bởi một đối tượng cơ sở mà họ đang nhìn lên (như trong ví dụ trên, nơi tài liệu tham khảo này đối tượng toàn cầu), ví dụ

foo.bar 

sẽ được chia thành foothanh. Thứ nhất, foo sẽ được giải quyết trên chuỗi phạm vi và nếu được tìm thấy, độ phân giải của tài sản sẽ cố gắng tìm một thuộc tính thanh. Vì vậy, đối với các thuộc tính, bạn có thể trực tiếp đối tượng nào được xem xét.Vì vậy, nếu có hai đối tượng có cùng thuộc tính được đặt tên, bạn có thể tra cứu cả hai thuộc tính miễn là cả hai đối tượng đều nằm trong phạm vi.

Vì vậy, phần đầu tiên của bất kỳ tham chiếu nào được coi là biến, các phần tiếp theo được coi là thuộc tính. Ngoại trừ khi với được sử dụng, nhưng điều đó không được khuyến khích. Đừng đi đến đó.

Nhưng cho đầy đủ ... với nơi các đối tượng quy định trên chuỗi phạm vi start để biến được đầu tiên nhìn lên như là tài sản của đối tượng đó trước khi sử dụng chuỗi phạm vi, vì vậy bạn có thể làm:

var cos = function(arg){return 'my cos function: ' + arg}; 

function foo() { 

    // cos is resolved on the scope chain 
    console.log(cos(0.5)); // my cos function: 0.5 

    with (Math) { 
    // cos is first resolved as a property of Math, and only on the 
    // scope chain if not found there 
    console.log(cos(0.5)) // 0.8775825618903728 
    } 
} 

foo(); 
Các vấn đề liên quan