2011-07-01 27 views
14

Cố gắng hiểu cách thức hoạt động của phiên bản CoffeeScript và biến lớp học mà tôi đi kèm với mã này (và kết quả có trong nhận xét).Đóng gói và truy cập biến thể CoffeeScript

class A 
    x: 1 
    @y: 2 

    constructor: (@z) -> 
    #console.log "const x", x #ReferenceError: x is not defined 
    console.log "constructor y", @y #undefined 
    console.log "constructor z", @z # = 3 for A and 6 for B 

    get:() -> 
    #console.log "get x", x #ReferenceError: x is not defined 
    console.log "get y", @y #undefined 
    console.log "get z", @z # = 3 for A and 6 for B 

    get2:() => 
    #console.log "get2 x", x #ReferenceError: x is not defined 
    console.log "get2 y", @y #undefined 
    console.log "get2 z", @z # = 3 for A and 6 for B 

    @get3:() -> 
    #console.log "get3 x", x #ReferenceError: x is not defined 
    console.log "get3 y", @y # = 2 
    console.log "get3 z", @z #undefined 

    @get4:() => 
    #console.log "get4 x", x #ReferenceError: x is not defined 
    console.log "get4 y", @y # = 2 
    console.log "get4 z", @z #undefined 

class B extends A 
    constructor: (@w) -> 
    super(@w) 

console.log '------A------' 
i = new A 3 
console.log "i.x", i.x # = 1 
console.log "i.y", i.y #undefined 
console.log "i.z", i.z # = 6 
i.get() 
i.get2() 
A.get3() 
A.get4() 
console.log '------B------' 
i = new B 6 
console.log "i.x", i.x # = 1 
console.log "i.y", i.y #undefined 
console.log "i.z", i.z # = 6 
console.log "i.w", i.w # = 6 
i.get() 
i.get2() 
B.get3() 
B.get4() 
console.log '------------' 

Có một số điều kỳ lạ xảy ra ở đây:

  1. x var Tôi đã chờ đợi để truy cập nó từ bất kỳ phương pháp nhưng x var không thể được truy cập từ bất kỳ phương pháp hoặc constructor (ReferenceError) . Tôi chỉ có thể truy cập nó từ một thể hiện của A hoặc B (i.x). Tại sao vậy?

  2. @y var Tôi đã mong đợi nhận @y var value từ bất kỳ phương thức nào nhưng không có giá trị ở hầu hết các địa điểm (giá trị không xác định, không phải là ngoại lệ ReferenceError). @y có giá trị chỉ trên @ get3 và @ get4 (ví dụ phương pháp?). Nếu nó được xác định, tại sao tôi không thể có được giá trị của nó?

  3. @y và @z var Cả hai @y và @z là các biến mẫu, nhưng vì @z được khởi tạo trong hàm tạo nên nó có một hành vi khác biệt. @y là hợp lệ trên @ get3 và @ get4 và @z là hợp lệ khi nhận và get2. Một lần nữa, những gì đang xảy ra ở đây?

Điều tôi thực sự bối rối bởi những hành vi này. Mã này có đúng không? Vậy, tôi có nên tìm hiểu thêm về JS do CS tạo ra không?

Tks

Trả lời

15

Trong các phần chức năng, @ đề cập đến this và trong định nghĩa lớp, @ đề cập đến chính lớp đó chứ không phải nguyên mẫu.

Vì vậy, trong ví dụ trên, định nghĩa của @y đề cập đến A.y và không phải là A.prototype.y.Đó là khó khăn để tham khảo nó vì cách this là ràng buộc trong các cách khác nhau của phương pháp xác định. Bạn có thể truy cập nó bằng cách sử dụng @y từ các phương pháp có tên @get vì trong trường hợp này this luôn đề cập đến A.

Định nghĩa của x đề cập đến A.prototype.x và như vậy từ get phương pháp của bạn, bạn nên truy cập vào nó qua @x trong get1get2.

Là một hướng dẫn cơ bản, cố gắng không sử dụng @ bên ngoài của các cơ quan chức năng và tất cả mọi thứ sẽ có ý nghĩa hơn rất nhiều:

class A 
    constructor: (@a) -> 
    b: 2 
    tryStuff: => 
    console.log(@a) #will log whatever you initialized in the constructor 
    console.log(@b) #will log 2 

EDIT: bạn có thể xem xét các phương pháp định nghĩa là @something là phương pháp tĩnh của lớp đó, vì vậy bạn có thể gọi chúng với classname.something() nhưng là phương thức tĩnh, chúng không thể truy cập vào bất kỳ biến mẫu nào.

+0

Tuyệt vời! Tôi nghĩ rằng điều quan trọng nhất là ở đây: "Là một hướng dẫn cơ bản, cố gắng không sử dụng @ bên ngoài của cơ quan chức năng và tất cả mọi thứ sẽ làm cho rất nhiều ý nghĩa hơn" True! –

8

Để đáp lại câu hỏi của bạn:

  1. x = 1 trong cơ thể lớp sẽ tạo ra một biến có tên x trong cơ thể phạm vi. Nhưng x: 1 trong nội dung lớp xác định thuộc tính x trên nguyên mẫu. Nếu bạn thay đổi console.log x thành console.log @x, thì bạn sẽ nhận được 1.
  2. Trong nội dung lớp học, @ trỏ đến chính lớp đó. Trong hàm khởi tạo (và trong các phương thức được gọi là instance.method), nó trỏ tới cá thể cụ thể. Thay đổi console.log @y thành console.log A.y và bạn sẽ nhận được 2. (Bạn cũng có thể sử dụng @constructor để lấy tham chiếu đến lớp từ cá thể đó, vì trong JavaScript, lớp thực sự là hàm hàm dựng.)
  3. Vì hàm xây dựng trỏ đến cá thể, bạn đang đặt Ví dụ của z thuộc tính cho giá trị đã cho.

Và vâng, tôi khuyên bạn nên tìm hiểu cơ bản JavaScript Tôi biết đó là một chút lẻ cho @ có rất nhiều ý nghĩa khác nhau, nhưng nó làm cho rất nhiều ý nghĩa khi bạn hiểu JavaScript của this (một trong những phần phức tạp hơn của ngôn ngữ, để chắc chắn). Ngẫu nhiên, my book có nhiều thông tin hơn về điều này.

+1

Tks! Và BTW, tôi đã đặt hàng trước cuốn sách của bạn: D Hy vọng sớm nhận được nó! –

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