Kiểm soát thừa kế trong JS



  • Em có 1 cái object A . Bây giờ em muốn kiểm soát sao cho khi tạo một đối tượng A mới có tên là B thì cái New Object B này sẽ không thể thừa kế 1 số thuộc tính mà bên A có cũng như không thể truy cập được các dữ liệu trong A(một số thuộc tính và dữ liệu được ẩn - ở chế độ private mà bên ngoài không thể truy cập).

    var A = (function(data){
        this.getData = function(){
            return data;
        }
        this.getData2 = function(){
            return Math.random();
        }
        return this;
    }).call(A,6);
    var B = new A();
    B.getData2() //=> Làm ntn để object B không thể thừa kế cái getData2 này
    A.getData2() //=> Và chỉ có thể gọi function từ object A
    B.getData() //=> Làm ntn để cái này không return về 6,kiểu như trong B không được thừa hưởng cái biến data này vậy
    

    Vấn đề thứ 2 là em muốn hỏi về việc cấp quyền truy cập vào object :

    var obj1 = (function(){
         var data = 6;
         var rt = function(){ 
         }
         rt.back = function(){
             return data;
         }
        return rt;
    })();
    var obj2 = (function(){
        var data = obj1.back(); // Làm ntn để obj2 có thể có được quyền truy cập vào dữ liệu bên trong closure của obj1
        return {back_data:data}; // Must return 6
    })();
    var obj3 = (function(){
        var data = obj1.back(); // Còn obj3 thì không
        return {back_data:data};//Unwanted return 6
    })();
    

    Rất mong được giải đáp thắc mắc ! Cảm ơn mọi người ~~~


  • Global Moderator

    @achung0147 Ý tưởng của bạn phức tạp quá, mình chưa nhìn thấy nó kế thừa ở chỗ nào :D

    Như tình huống 1 của bạn thì B chỉ là thể hiện của A thôi. Bạn xem lại định nghĩa và các ví dụ về kế thừa trong JavaScript ở đây nhé

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

    Tech-nông
    Twitter: @nhubaovu
    Profile: about.me/vunb

    0


  • @achung0147 thực sự thì có thể làm đc nhưng ko nên. Ví dụ:

    var assert = require('assert');
    log = console.log;
    
    var A = (function() {
    	var _A = function(data) {
    		this.data = data;
    	}
    	_A.getData = function() {
    		return this.data;
    	}
    	_A.getRandom = function() {
    		return Math.random();
    	}
    	_A.prototype.hello = function(){
    		log('hello from B');
    	}
    
    	return _A;
    })();
    
    var B = new A();
    // assert 
    assert(B.getData == undefined, 'B.getData is inherited'); 
    assert(A.getData instanceof Function,'A.getData is not a Function'); 
    assert(B.getRandom == undefined ,'B.getRandom is inherited'); 
    assert(B.hello  instanceof Function,'B.hello is not a Function'); 
    
    // log test
    // A.hello(); // Error 
    // B.getData(); // Error 
    // B.getRandom(); // Error 
    log(A.getRandom());
    B.hello();
    
    

    Mình nghĩ bạn nên viết function riêng rẽ, khi cần thì import vào đối tượng thì hay hơn.



  • Bạn xem qua về "Closure" trong Js, private function có thể được viết như sau

    function wrapper {
    var a = function a () { }
    var b = function b () { }
    return { b }
    }

    ... function a sẽ là private



  • @achung0147 Bạn nên diễn tả ý tưởng bằng lời thì hơn:
    Ý 1: Cần tạo đối tượng A có nhiệm vụ tạo ra đối tượng B và có những thuộc tính và phương thức B sẽ không được thừa hưởng từ A.
    Ý 2: Cần tạo ra đối tượng A chứa dữ liệu và cấp quyền truy cập cho các đối tượng khác. Ví dụ B được truy cập còn C không.
    Có phải ý bạn vậy không?



  • @Phuc-Phan66 đúng rồi ạ



  • @achung0147
    Có đoạn mã cần chú ý giả sử chạy trong Global thì nó thế này.

    var A = (function(data) {
    	// Cái "this" ở trong này chính là  Global nếu ở chế độ strict mode sẽ là null hoặc undefined.
    
        this.getData = function() {
            return data;
        }
        this.getData2 = function() {
            return Math.random();
        }
        return this;
    }).call(A, 6)
    //Bạn đã chạy nó
    

    tương tự mã của @hidemanvn nếu không may gọi hàm:

    A("number");    //sẽ xuất hiện (Global).data = 'number'; có thể nó không bao giờ được gọi
    

    Có thể mình không hiểu hoặc hiểu nhầm ý của bạn chỉ là đề xuất một số mã nhỏ.
    Cái này sửa một chút mã thứ hai của bạn:

    var obj1 = (function() {
        var data = 6;
        var rt = function() {}
        rt.back = function() {
            var callName = arguments.callee.caller.name;
            if (callName == "createTypeObj2") {
                return data;
            }
            if (callName !== "createTypeObj2") {
                return "Không phải 6";
    
            }
        }
        return rt;
    })();
    
    function createTypeObj2() {
        var data = obj1.back(); // Làm ntn để obj2 có thể có được quyền truy cập vào dữ liệu bên trong closure của obj1
        return {
            back_data: data
        }; // Must return 6
    };
    
    function createTypeObj3() {
        var data = obj1.back(); // Còn obj3 thì không
        return {
            back_data: data
        }; //Unwanted return 6
    };
    var obj2 = createTypeObj2();
    var obj3 = createTypeObj3();
    
    /*Test*/
    console.log(obj2);   // {back_data: 6}
    console.log(obj3);	 // {back_data: "Không phải 6"}
    


  • Về ý thứ nhất của ban:
    //=> Làm ntn để object B không thể thừa kế cái getData2 này
    Bạn đừng viết constructor và prototypes có nó.
    //=> getData2 Và chỉ có thể gọi function từ object A
    Bạn đừng viết constructor và prototypes có nó.
    Mà tạo trực tiếp là A.getData2 = xyz..;
    //=> Làm ntn để cái này không return về 6,kiểu như trong B không được thừa hưởng cái biến data này vậy
    Bạn phải thiết lập nó return cái bạn muốn.
    //Tránh việc "this" vô tình tham chiếu Global nên thêm một đoạn mã kiểu như thế này cho constructor :

    function A() {
        if (!(this instanceof A))
            return new A();
    }
    


  • @Phuc-Phan66 mình viết ví dụ vậy thôi chứ thực tế làm việc thì chẳng bao giờ mình để hàm nó ngoài vòng global đâu. Mình gặp trường hợp này thì mình chia nhỏ function hoặc xác định object con rồi import vào object.


Log in to reply