2012-10-20 38 views
9

Tôi muốn lồng một số hàm bên trong một thuộc tính lớp như được hiển thị bên dưới.
Thật không may, họ sẽ không có quyền truy cập vào phạm vi chính của lớp học.Phạm vi trong các lớp học coffeescript

Tôi có thể giải quyết điều này mà không phải chuyển từng hàm lồng nhau tham chiếu đến this?

class myClass 

    constructor: -> @errors = [] 

    doSomething: -> @errors.push "I work as expected" 

    functions: 
    doStuff: -> 
     @errors.push "I cant access @errors" # => TypeError: Cannot call method 'push' of undefined 

    ugly: (context) -> 
     context.errors.push "It works, but I am ugly" # Works fine but requires scope injection 

không làm việc thay thế bằng cách sử dụng gợi ý mũi tên chất béo:

class myClass 
    constructor: -> 
    @errors = [] 

    @functions: 
     doStuff: => 
     @errors.push "I wont work either" # TypeError: Cannot call method 'toString' of undefined 

Tùy chọn thay thế, mà không viết thư cho toàn cầu this.errors tài sản:

class myClass 

    constructor: -> 

    @functions = 
     errors: [] 
     doStuff: -> 
     @errors.push "I will write to functions.errors only" 
+0

Binding chúng vào/@ này trong hàm tạo? – biziclop

+0

Bạn có nghĩa là 'hàm tạo: -> @errors = [] @functions: doStuff -> ...'? – Industrial

+0

Có thể sử dụng mũi tên chất béo => http://coffeescript.org/#fat_arrow Tôi không phải là chủ nhân coffeescript, xin lỗi :) – biziclop

Trả lời

3

Trong JavaScript (như kết quả , CoffeeScript quá), các phương thức sử dụng this của đối tượng chứa phương thức.

method()     // this == globalObject 
object.method()   // this == object 
Math.random()    // this == Math 

này thường hoạt động tốt, trừ khi bạn đối phó với ví dụ như của bạn:

object.functions.method() // this == object.functions 

Khi giao dịch với Javascript, tôi sẽ tránh việc namespace cho các chức năng - nó không chơi tốt, ngay cả với cách giải quyết . Ví dụ: bạn có thể thử đặt tham chiếu đến đối tượng this trong object.functions, vì vậy, mọi chức năng trong object.functions sẽ có quyền truy cập vào đối tượng đó.

class MyClass 
    constructor: -> 
    @errors = [] 
    @functions.self = this 

    doSomething: -> 
    @errors.push "I work as expected" 

    functions: 
    alsoDoSomething: -> 
     @self.errors.push "Also works!" 

Điều này dường như làm việc lúc đầu, nhưng có thể gây nhầm lẫn khi bạn đang sử dụng tài sản như apply hoặc call vào nó, obj1.functions.alsoDoSomething.call(obj2) sẽ không làm việc như obj2 là không đúng đối tượng (người dùng nên làm obj2.functions thay vì đó có thể gây nhầm lẫn).

Giải pháp thực tế là: không. JavaScript không có ý định lạm dụng như thế này. Tất cả các phương thức đối tượng nên được trực tiếp trong nguyên mẫu đối tượng. Nếu bạn có đối tượng trong đó, tất cả các phương thức của nó không phải là các phương thức của đối tượng của bạn.

+0

Cảm ơn bạn đã giải thích và giải quyết tuyệt vời! – Industrial

2

Là phụ lục cho câu trả lời của GlitchMr, tôi sẽ giải thích lý do tại sao mỗi lần thử của bạn thất bại.

  1. Đối tượng functions được khai báo trên nguyên mẫu, do đó @errors được biên dịch thành myClass.errors. Tuy nhiên, đối tượng errors được khai báo là thành viên cá thể chứ không phải thành viên mẫu.
  2. Bạn xác định functions sử dụng ký pháp chức năng của CoffeeScript, khi nó phải là một đối tượng. Thông báo lỗi là lỗi trình biên dịch CoffeeScript; sau khi sửa lỗi cú pháp này, nó hoạt động như nó nên!
  3. Bạn mở đầu ví dụ này với lý do tại sao nó không hoạt động, vì vậy tôi sẽ không nói cho bạn hai lần!

Dưới đây là ví dụ về việc sử dụng chính xác số fat arrow trong trường hợp này.

class MyClass 

    constructor: -> 
    @errors = [] 
    @functions = 
     doStuff: => 
     @errors.push "I can and do access @errors" 

c = new MyClass 
c.functions.doStuff() 
console.log c.errors # ["I can and do access @errors"] 

Hy vọng điều này sẽ giúp làm sáng tỏ lỗi và thể hiện sức mạnh của mũi tên chất béo của CoffeeScript!

+0

Cảm ơn bạn đã giải thích '=>' – Industrial

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