2011-09-27 28 views
12

Trong chế độ xem xương sống, nơi bạn sẽ đặt các biến riêng tư và công khai của mình.Biến cá nhân và công khai vào chế độ xem xương sống

Ngay bây giờ tôi có một cái gì đó như thế này:

myView = Backbone.View.extend({ 

    initialize: function(options){ 
    this.myPublic = "I'm public"; 
    } 

}); 

tôi đã cố gắng thêm một var myPrivate trước khi phương pháp khởi tạo nhưng nó ném một lỗi. Các biến riêng tư chỉ được sử dụng trong chế độ xem sẽ đi đâu?

+0

Ông có thể giải thích tại sao bạn đang cố gắng làm điều này? Không thực sự là một giải pháp thẳng tiến. – Gazler

+0

không nhiều để giải thích appart từ làm thế nào tôi có thể thêm một tài sản tư nhân để xem. Ví dụ var myPrivate = "tài sản riêng" nhưng nó sẽ có sẵn cho toàn bộ khung nhìn giống như this.myPublic. Ngoại trừ this.myPublic có thể được truy cập từ cá thể xem. myPrivate chỉ có thể được truy cập từ bên trong các phương thức xem chính nó – Chapsterj

+1

Xem câu trả lời này: http: // stackoverflow.com/questions/8924961/private-like-properties-in-models-hoặc-views-of-backbone-js –

Trả lời

11

Wrap nó tất cả lên trong một chức năng ẩn danh tự gọi:

(function() { 
    var myPrivate = 1; 

    myView = Backbone.View.extend({ 
     initialize: function(options){ 
      this.myPublic = "I'm public"; 
      myPrivate++; 
     }, 
     render: function() { 
      alert(myPrivate); 
     } 
    }); 

})(); 

Edit: Như đã chỉ ra trong kaustubh's comment dưới đây, ví dụ trên tạo ra một biến tin được chia sẻ giữa các trường hợp. Bạn có thể tạo một loại biến số được bảo vệ, tức là một biến cấp độ thể hiện có thể được đọc bởi các phiên bản khác của Chế độ xem. Cho mỗi cá thể một id công khai duy nhất và lưu các biến cá thể trong một biến "tĩnh riêng". Sau đó truy cập vào các biến bằng cách dụ id:

(function() { 
    var data = []; 

    myView = Backbone.View.extend({ 
     initialize: function(options){ 
      this.myPublic = "I'm public"; 
      this.Id = data.length; 
      data.push({}); 
      data[this.Id].myProtected = "abc"; 
     }, 
     render: function() { 
      alert(data[this.Id].myProtected) 
     } 
    }); 
})(); 

Hoặc, bạn có thể làm điều đó mà không cần sử dụng một id công cộng, nhưng nó trở nên một chút phức tạp hơn:

(function() { 
    var data = (function() { 
     var dataValues = []; 
     return function (instance) { 
      for (var i = 0; i < dataValues.length; i++) { 
       if (dataValues[i].instance === instance) { 
        return dataValues[i].data; 
       } 
      } 
      var dataObject = { instance: instance, data: {} }; 
      dataValues.push(dataObject); 
      return dataObject.data; 
     }; 
    })(); 

    myView = Backbone.View.extend({ 
     initialize: function(options){ 
      this.myPublic = "I'm public"; 
      data(this).myProtected = "abc"; 
     }, 
     render: function() { 
      alert(data(this).myProtected) 
     } 
    }); 
})(); 

Tôi đang đấu tranh để đưa ra một cách để lưu trữ các biến thực sự riêng tư. Tôi sẽ đăng lại nếu cảm hứng xảy ra.

+0

Đừng quên dấu ngoặc ở cuối để thực sự làm cho nó tự gọi. – Gazler

+0

@Gazler - Tốt, cảm ơn! – gilly3

+0

Cảm ơn Gazler, Làm thế nào bạn sẽ tạo ra một thể hiện của khung nhìn này. hoặc làm thế nào bạn sẽ có thể tham chiếu nó để tạo ra một thể hiện của xem – Chapsterj

19

Tôi đề nghị bạn sử dụng phương pháp khởi tạo như là một bao đóng xung quanh tất cả các phương pháp khác. Tôi nghĩ rằng điều này sẽ cung cấp cho bạn hành vi phù hợp hơn với những gì chúng tôi nhận được trong các ngôn ngữ kế thừa cổ điển như C++ và Java:

 

myView = Backbone.View.extend({ 

    initialize: function(options){ 
    var myPrivate = "I'm private"; 

    this.myPublic = "I'm public"; 

    this.getPrivate = function() { 
     return myPrivate; 
    }; 

    this.setPrivate = function (value) { 
     if (typeof(value) === 'string') { 
      myPrivate = value; 
      return true; 
     } else { 
      return false; 
     } 
    }; 
    } 
}); 
+0

Không thêm các phương thức bên trong khởi tạo sử dụng biến riêng tư, làm cho khởi tạo chậm hơn mỗi đối tượng thời gian tạo ra? –

+1

@StalinGino Có. Tôi không biết đó có phải là một sự chậm lại mà bất cứ ai cũng cảm thấy, nhưng nó chắc chắn sẽ chiếm nhiều không gian hơn trong ký ức. – pilau

-2

Sử dụng "này"?

 

    initialize:function() { 
     this.viewpointers = {} 
    }, 
    render:function() { 
     var self = this 
     _.each(this.viewpointers, function(item){ 
      self.$el.find(".assigned-items").append(item.render().el) 
     }); 
    } 

thêm chúng. Sau đó, đây là những bảo vệ atleast. giải pháp

 

    this.viewpointers[model.id] = new view({model:model}) 

0

gilly3 có thể là câu trả lời tốt nhất, mặc dù nó không phải là về mặt kỹ thuật tạo/sử dụng một biến tư nhân vì trường hợp khác của việc đóng cửa tương tự sẽ được tiếp cận với nó (có thể bạn không phải là quan tâm đến các thành viên khác của bạn nhóm phát triển lạm dụng đặc quyền đó, nhưng điều đó có thể xảy ra).

Nếu bạn muốn sử dụng biến tư nhân mà không sử dụng cách tiếp cận gilly3 của, câu trả lời gần Privman dường như là giải pháp đúng đắn duy nhất như Douglas Crockford giải thích làm thế nào để tạo ra các biến tin ở đây: http://javascript.crockford.com/private.html

này sẽ bổ sung thêm thời gian xử lý javascript từ nó sẽ không thể sử dụng sự thừa kế nguyên mẫu và sẽ sử dụng tài nguyên để tái tạo lại chức năng mỗi lần.

Tuy nhiên, đây có thể không phải là một vấn đề rất đáng chú ý nếu đóng cửa bạn tạo ra mỗi lần là rất nhỏ hoặc nếu số lần một cá thể mới được tạo ra là tối thiểu. Trong nỗ lực để cố gắng tận dụng tối đa cả hai thế giới, bạn có thể ủy thác phần lớn phương pháp sử dụng biến riêng (via delegation pattern) cho một hàm tĩnh sẽ không được tạo lại mỗi lần. Điều này sẽ rời khỏi phương thức publicMethodThatUsesPrivateVariable được hiển thị bên dưới nhỏ hơn, có nghĩa là sẽ mất ít thời gian hơn để tạo lại mỗi lần.

var _privateStaticMethod = function(privateVariableValue, methodParameter) { 
     var result; 

     // Execute the lengthy javascript logic here ... 

     result = Math.ceil(privateVariableValue/108); 
     result += 4815162342; 
     return result; 
    }; 

    Backbone.View.extend({ 
     initialize: function() { 
      var _privateVariable = 303; 

      this.publicMethodThatUsesPrivateVariable = function(methodParameter) { 
       // Only place as little logic as you can here outside of the private static method being used below 
       _privateVariable += 1; 

       return _privateStaticMethod(_privateVariable, methodParameter); 
      }; 
     }, 

     // ... 
    }); 

Lưu ý rằng mã ở trên cũng phải được bao bọc trong một số chức năng để _privateStaticMethod không phải là biến toàn cầu/chức năng.

1

Thay vì chèn đối tượng trực tiếp vào chức năng mở rộng, cách tạo một đóng và đóng cửa đó sẽ trả về một đối tượng cho hàm mở rộng?

var myView = Backbone.View.extend(function() { 

    var _myPrivateOne = 0; 

    function _myPrivateStrangeSquareFunction(a) { 
    return a * a + 1; 
    } 

    return { 
    initialize: function (options) { 
     _myPrivateOne = options.privateOne; 
     this.myPublicOne = options.publicOne; 
    }, 
    setPrivateOne: function (value) { 
     _myPrivateOne = value; 
     return _myPrivateOne; 
    }, 
    getPrivateOne: function() { 
     return _myPrivateOne; 
    }, 
    getPrivateOneStrangelySquared: function() { 
     return _myPrivateStrangeSquareFunction(_myPrivateOne); 
    } 
    }; 

}()); 

Tôi chưa thử điều này, vì hiện tại tôi không có bản cài đặt Backbone.

+0

Bây giờ tôi nhận ra rằng các biến riêng tư này sẽ được chia sẻ bởi nhiều phiên bản của Chế độ xem này. Bản sửa lỗi cho điều này sẽ là: _privates = {}; _privates [this.cid] = {}; // Đối tượng để lưu trữ các công cụ riêng cho đối tượng cụ thể (bằng cid). – jgroenen

0

Tôi thích câu trả lời của Near Privman cho đến khi tôi gặp sự cố với việc ghi đè phương thức "siêu". Vì initialize() không được gọi cho đến khi một số cách thông qua việc xây dựng một đối tượng Backbone, việc ghi đè có thể không xảy ra vào thời điểm cần thiết (nếu cần trước initialize()).

Cụ thể, điều này có thể là vấn đề với parse(). (. Không phải là một vấn đề đối với Views, nhưng chắc chắn cho bộ sưu tập và các mô hình) Với thiết lập này:

MyModel = Backbone.Model.extend({ 
    initialize: function (options) { 
     this.parse = function (response, xhr) { 
      // parsing logic 
     }; 

     // public & private vars/methods here 
     // and also initialize code 
    } 
}); 

MySubModel = MyModel.extend({ 
    initialize: function (options) { 
     this.parse = function (response, xhr) { 
      // override MyModel with my own parsing logic 
     } 

     // public & private vars/methods here 
     // and initialize code here 
    } 
}); 

MySubModel.parse() sẽ không bao giờ được gọi. Thay vào đó, tôi thấy rằng sử dụng IIFE thay vì khởi tạo() cả hai đều xóa vấn đề này và đọc sạch hơn là thực hiện một chức năng đã có mục đích cụ thể (initialize()) thực hiện nhiệm vụ gấp đôi làm đóng cửa để xác định phần còn lại của lớp.

var MyModel = {}; 
(function() { 
    this.initialize = function (attributes, options) { 
     // initialize me 
    } 

    this.parse = function (response, xhr) { 
     // override at will 
    } 

    // other public & private vars/methods here 
}).call(MyModel); 

Backbone.Model.extend(MyModel); 

Thật không may, điều này có cùng vấn đề với biến "riêng tư" được chia sẻ trên tất cả các trường hợp như cả câu trả lời của gilly3 và Near Privman. Rất thích nghe một cách không vụng về để biến các biến riêng tư thành có thể, nhưng có lẽ tôi nên từ bỏ nó và nhận ra tôi đang viết JavaScript ngay bây giờ, không phải Java/AS3/C++.

0

Bạn có thể thử này:

var Thing = Backbone.Model.extend(
    { 
     constructor : function() 
     { 
      var _value = "Private data!"; 

      this.getValue = function() 
      { 
       console.log(_value); 
      }; 
      this.setValue = function (value) 
      { 
       _value = value; 
      }; 
     } 
    }); 
0

The Backbone cách tiêu chuẩn của việc thêm các biến "tin" là tuyên bố họ như là thuộc tính với một dấu gạch dưới "_" trước mặt họ. Chúng không thực sự riêng tư, nhưng các nhà phát triển sẽ nhận ra rằng chúng không được sử dụng công khai.

Điều này, trên thực tế, là cách Backbone lưu trữ các biến riêng của riêng mình.

0

Trong bối cảnh của việc sử dụng Broserify.js với Backbone (và thực sự bất kỳ ở trên dự án trung bình) tôi thấy cách sau đây để có vars tin và các chức năng:

myView.js

'use strict'; 

var config  = require('../config.js'), 

    private_var = 'private variable', 
    my_private_fn = function() { 
     ... 
    }; 


module.exports = Backbone.Model.extend({ 
    initialize: function() { 
     this.my_public = 'public variable'); 

     console.log('This is my' + this.my_public); 
     console.log('This is my' + my_private); 
    }, 
}); 
Các vấn đề liên quan