programing

JavaScript 개인 메서드

coolbiz 2022. 9. 18. 22:38
반응형

JavaScript 개인 메서드

공개 메서드를 사용하여 JavaScript 클래스를 만들려면 다음과 같은 작업을 수행합니다.

function Restaurant() {}

Restaurant.prototype.buy_food = function(){
   // something here
}

Restaurant.prototype.use_restroom = function(){
   // something here
}

이를 통해 내 클래스 사용자는 다음을 수행할 수 있습니다.

var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();

" " " " 에서 할 수 해야 ?buy_food ★★★★★★★★★★★★★★★★★」use_restroom외부적으로는 클래스 사용자가 아닌 방법?

즉, 메서드 구현이 다음을 수행할 수 있기를 바랍니다.

Restaurant.prototype.use_restroom = function() {
   this.private_stuff();
}

하지만 이렇게 하면 안 됩니다.

var r = new Restaurant();
r.private_stuff();

「 」의 정의 private_stuff둘다다다다???????

Doug Crockford의을 몇 번 읽었지만, "프라이빗" 방식은 공공적인 방법으로 호출할 수 있고 "특권" 방식은 외부적으로 호출할 수 있는 것 같지 않습니다.

할 수 있지만, 단점은 프로토타입에 포함될 수 없다는 것입니다.

function Restaurant() {
    var myPrivateVar;

    var private_stuff = function() {  // Only visible inside Restaurant()
        myPrivateVar = "I can set this here!";
    }

    this.use_restroom = function() {  // use_restroom is visible to all
        private_stuff();
    }

    this.buy_food = function() {   // buy_food is visible to all
        private_stuff();
    }
}

자동 호출 기능 및 호출 사용

JavaScript는 프로토타입을 사용하며 Object Oriented 언어와 같은 클래스(또는 메서드)를 가지고 있지 않습니다.JavaScript 개발자는 JavaScript에서 생각해야 합니다.

위키피디아 인용문:

많은 객체 지향 언어와 달리 함수 정의와 메서드 정의 사이에는 차이가 없습니다.오히려 함수를 호출할 때 구별이 발생합니다.함수가 객체의 메서드로 호출될 때 함수의 local 이 키워드는 호출을 위해 해당 객체에 바인딩됩니다.

자가 호출 함수와 호출 함수를 사용하여 개인 "메서드"를 호출하는 솔루션:

var MyObject = (function () {
    
  // Constructor
  function MyObject(foo) {
    this._foo = foo;
  }

  function privateFun(prefix) {
    return prefix + this._foo;
  }
    
  MyObject.prototype.publicFun = function () {
    return privateFun.call(this, ">>");
  }
    
  return MyObject;

}());
var myObject = new MyObject("bar");
myObject.publicFun();      // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined

함수를 사용하면 적절한 컨텍스트를 사용하여 프라이빗 함수를 호출할 수 있습니다(this를 참조해 주세요.

Node.js로 심플화

Node.js를 사용하는 경우 모듈 로딩 시스템을 이용할 수 있기 때문에 IIE는 필요하지 않습니다.

function MyObject(foo) {
  this._foo = foo;
}
    
function privateFun(prefix) {
  return prefix + this._foo;
}

MyObject.prototype.publicFun = function () {
  return privateFun.call(this, ">>");
}
    
module.exports= MyObject;

파일을 로드합니다.

var MyObject = require("./MyObject");
    
var myObject = new MyObject("bar");
myObject.publicFun();      // Returns ">>bar"
myObject.privateFun(">>"); // ReferenceError: private is not defined

(신규!) 향후 JavaScript 버전에서의 네이티브 개인 메서드

JavaScript 클래스 제안을 위한 TC39 개인 메서드getter/setter는 3단계입니다.이는 곧 JavaScript가 개인 메서드를 네이티브로 구현한다는 것을 의미합니다.

JavaScript 개인 클래스 필드는 최신 버전의 JavaScript에 이미 존재합니다.

다음은 사용 방법의 예입니다.

class MyObject {

  // Private field
  #foo;
    
  constructor(foo) {
    this.#foo = foo;
  }

  #privateFun(prefix) {
   return prefix + this.#foo;
  }
    
  publicFun() {
    return this.#privateFun(">>");
  }

}

오래된 JavaScript 엔진에서 이 코드를 실행하려면 JavaScript 트랜스파일러/컴파일러가 필요할 수 있습니다.

:: ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」#프리픽스, 읽어주세요.

(권장되지 않음) ES7(바인드 오퍼레이터 포함)

경고:바인드 연산자 TC39 프로포지션은 거의 데드상태입니다.https://github.com/tc39/proposal-bind-operator/issues/53#issuecomment-374271822

연산자 " " "::ECMAScript 제안으로 Babel(0단계)에서 구현됩니다.

export default class MyObject {
  constructor (foo) {
    this._foo = foo;
  }

  publicFun () {
    return this::privateFun(">>");
  }
}

function privateFun (prefix) {
  return prefix + this._foo;
}

다음과 같이 개인 방식을 시뮬레이션할 수 있습니다.

function Restaurant() {
}

Restaurant.prototype = (function() {
    var private_stuff = function() {
        // Private code here
    };

    return {

        constructor:Restaurant,

        use_restroom:function() {
            private_stuff();
        }

    };
})();

var r = new Restaurant();

// This will work:
r.use_restroom();

// This will cause an error:
r.private_stuff();

이 기술에 대한 자세한 내용은http://http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html 를 참조해 주세요.

퍼블릭 API가 있고 프라이빗 및 퍼블릭메서드/프로퍼티가 필요한 경우 항상 Module Pattern을 사용합니다.이 패턴은 YUI 라이브러리 내에서 널리 보급되었습니다.상세한 것은, 이하를 참조해 주세요.

http://yuiblog.com/blog/2007/06/12/module-pattern/

이것은 매우 간단하고 다른 개발자들이 이해하기 쉽습니다.간단한 예:

var MYLIB = function() {  
    var aPrivateProperty = true;
    var aPrivateMethod = function() {
        // some code here...
    };
    return {
        aPublicMethod : function() {
            aPrivateMethod(); // okay
            // some code here...
        },
        aPublicProperty : true
    };  
}();

MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay

이것은 더글라스 크록포드가 자바스크립트에서 개인 멤버에게 제안한 내용을 이해하기 위해 만든 클래스입니다.

function Employee(id, name) { //Constructor
    //Public member variables
    this.id = id;
    this.name = name;
    //Private member variables
    var fName;
    var lName;
    var that = this;
    //By convention, we create a private variable 'that'. This is used to     
    //make the object available to the private methods. 

    //Private function
    function setFName(pfname) {
        fName = pfname;
        alert('setFName called');
    }
    //Privileged function
    this.setLName = function (plName, pfname) {
        lName = plName;  //Has access to private variables
        setFName(pfname); //Has access to private function
        alert('setLName called ' + this.id); //Has access to member variables
    }
    //Another privileged member has access to both member variables and private variables
    //Note access of this.dataOfBirth created by public member setDateOfBirth
    this.toString = function () {
        return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth; 
    }
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
    alert('setDateOfBirth called ' + this.id);
    this.dataOfBirth = dob;   //Creates new public member note this is accessed by toString
    //alert(fName); //Does not have access to private member
}
$(document).ready()
{
    var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
    employee.setLName('Bhaskar', 'Ram');  //Call privileged function
    employee.setDateOfBirth('1/1/2000');  //Call public function
    employee.id = 9;                     //Set up member value
    //employee.setFName('Ram');  //can not call Private Privileged method
    alert(employee.toString());  //See the changed object

}

ES12 개인 방식

작업은 es12의 프라이빗 메서드로 실행할 수 있습니다.추가만 하면 됩니다.#메서드 이름 앞에 표시됩니다.

class ClassWithPrivateMethod {
  #privateMethod() {
    return 'hello world';
  }

  getPrivateMessage() {
    return #privateMethod();
  }
}

생각해 낸 것은, 「편집」입니다.실제로, 누군가가 같은 솔루션에 링크 하고 있습니다.윽!

var Car = function() {
}

Car.prototype = (function() {
    var hotWire = function() {
        // Private code *with* access to public properties through 'this'
        alert( this.drive() ); // Alerts 'Vroom!'
    }

    return {
        steal: function() {
            hotWire.call( this ); // Call a private method
        },
        drive: function() {
            return 'Vroom!';
        }
    };
})();

var getAwayVechile = new Car();

hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'

ES2021/ES12: 프라이빗 메서드

은 해시(hash)로합니다.#prefix로 정의되어 있는 클래스 내에서만 액세스 할 수 있습니다.

class Restaurant {

  // private method
  #private_stuff() {
    console.log("private stuff");
  }

  // public method
  buy_food() {
    this.#private_stuff();
  }

};

const restaurant = new Restaurant();
restaurant.buy_food(); // "private stuff";
restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function

폐쇄에 대한 이해가 부족하기 때문에 그런 질문들이 계속 나오고 있다고 생각합니다.①JS에서는 인클로저가 가장 중요합니다.모든 JS 프로그래머는 그 본질을 느껴야 합니다.

1. 우선 범위(폐쇄)를 분리할 필요가 있다.

function () {

}

2. 이 지역에서는 우리가 원하는 것은 무엇이든 할 수 있어요.아무도 모를 거야

function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
}

3. 레스토랑 클래스를 세계에 알리기 위해서는 폐업에서 되돌려야 합니다.

var Restaurant = (function () {
    // Restaurant definition
    return Restaurant
})()

4. 마지막에는 다음과 같은 이 있습니다.

var Restaurant = (function () {
    var name,
        secretSkills = {
            pizza: function () { return new Pizza() },
            sushi: function () { return new Sushi() }
        }

    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return name in secretSkills ? secretSkills[name]() : null
    }
    return Restaurant
})()

5. 또한 이 접근법은 상속과 템플릿 제작의 가능성이 있다.

// Abstract class
function AbstractRestaurant(skills) {
    var name
    function Restaurant(_name) {
        name = _name
    }
    Restaurant.prototype.getFood = function (name) {
        return skills && name in skills ? skills[name]() : null
    }
    return Restaurant
}

// Concrete classes
SushiRestaurant = AbstractRestaurant({ 
    sushi: function() { return new Sushi() } 
})

PizzaRestaurant = AbstractRestaurant({ 
    pizza: function() { return new Pizza() } 
})

var r1 = new SushiRestaurant('Yo! Sushi'),
    r2 = new PizzaRestaurant('Dominos Pizza')

r1.getFood('sushi')
r2.getFood('pizza')

나는 이것이 누군가가 이 주제를 더 잘 이해하는데 도움이 되기를 바란다.

개인적으로 JavaScript에서 클래스를 만들 때는 다음과 같은 패턴을 선호합니다.

var myClass = (function() {
    // Private class properties go here

    var blueprint = function() {
        // Private instance properties go here
        ...
    };

    blueprint.prototype = { 
        // Public class properties go here
        ...
    };

    return  {
         // Public class properties go here
        create : function() { return new blueprint(); }
        ...
    };
})();

보시는 바와 같이 클래스 속성과 인스턴스 속성을 모두 정의할 수 있습니다.클래스 속성과 인스턴스 속성은 각각 퍼블릭 및 프라이빗일 수 있습니다.


데모

var Restaurant = function() {
    var totalfoodcount = 0;        // Private class property
    var totalrestroomcount  = 0;   // Private class property
    
    var Restaurant = function(name){
        var foodcount = 0;         // Private instance property
        var restroomcount  = 0;    // Private instance property
        
        this.name = name
        
        this.incrementFoodCount = function() {
            foodcount++;
            totalfoodcount++;
            this.printStatus();
        };
        this.incrementRestroomCount = function() {
            restroomcount++;
            totalrestroomcount++;
            this.printStatus();
        };
        this.getRestroomCount = function() {
            return restroomcount;
        },
        this.getFoodCount = function() {
            return foodcount;
        }
    };
   
    Restaurant.prototype = {
        name : '',
        buy_food : function(){
           this.incrementFoodCount();
        },
        use_restroom : function(){
           this.incrementRestroomCount();
        },
        getTotalRestroomCount : function() {
            return totalrestroomcount;
        },
        getTotalFoodCount : function() {
            return totalfoodcount;
        },
        printStatus : function() {
           document.body.innerHTML
               += '<h3>Buying food at '+this.name+'</h3>'
               + '<ul>' 
               + '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
               + '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
               + '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
               + '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
               + '</ul>';
        }
    };

    return  { // Singleton public properties
        create : function(name) {
            return new Restaurant(name);
        },
        printStatus : function() {
          document.body.innerHTML
              += '<hr />'
              + '<h3>Overview</h3>'
              + '<ul>' 
              + '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
              + '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
              + '</ul>'
              + '<hr />';
        }
    };
}();

var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");

Restaurant.printStatus();

Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();

Restaurant.printStatus();

BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();

Restaurant.printStatus();

바이올린을 참조하십시오.

이 모든 폐쇄에는 비용이 들 것이다.특히 IE에서 속도의 영향을 테스트해야 합니다.명명 규칙을 사용하는 것이 더 낫다는 것을 알게 될 것입니다.IE6를 사용해야 하는 기업 웹 사용자는 여전히 많습니다.

너무 장황하게 말하지 마세요.자바스크립트야명명 규칙을 사용합니다.

수년 동안 es6 클래스에서 일한 후 최근 es5 프로젝트를 시작했습니다(요구 사용).JS는 이미 매우 장황하게 보입니다.)여기서 언급한 모든 전략을 몇 번이고 검토했는데 기본적으로 명명 규칙을 사용하는 것으로 요약됩니다.

  1. 에는 Javascript와 같은 스코프 privateJavascript에 들어가는 다른 개발자들은 이것을 미리 알고 있을 것입니다.따라서 간단한 명명 규칙만으로도 충분합니다.언더스코어를 붙이는 간단한 명명 규칙을 사용하면 개인 속성과 개인 메서드의 문제를 해결할 수 있습니다.
  2. 속도 측면에서 프로토타입을 활용하되 더 이상 장황하게 설명하지는 마십시오.es5의 "클래스"를 다른 백엔드 언어에서 기대할 수 있는 것과 비슷하게 유지하도록 합시다(인스턴스를 반환할 필요가 없는 경우에도 모든 파일을 하나의 클래스로 취급합니다).
  3. 좀 더 현실적인 모듈 상황을 보여 드리겠습니다(구 es5 및 구 requireJs 사용).

마이 팁js

    define([
        'tooltip'
    ],
    function(
        tooltip
    ){

        function MyTooltip() {
            // Later, if needed, we can remove the underscore on some
            // of these (make public) and allow clients of our class
            // to set them.
            this._selector = "#my-tooltip"
            this._template = 'Hello from inside my tooltip!';
            this._initTooltip();
        }

        MyTooltip.prototype = {
            constructor: MyTooltip,

            _initTooltip: function () {
                new tooltip.tooltip(this._selector, {
                    content: this._template,
                    closeOnClick: true,
                    closeButton: true
                });
            }
        }

        return {
            init: function init() {
               new MyTooltip();  // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
            }

            // You could instead return a new instantiation, 
            // if later you do more with this class.
            /* 
            create: function create() {
               return new MyTooltip();
            }
            */
        }
    });

Crockford의 프라이빗 패턴 또는 기밀 패턴을 따르는 솔루션을 선택합니다.예를 들어 다음과 같습니다.

function Foo(x) {
    var y = 5;
    var bar = function() {
        return y * x;
    };

    this.public = function(z) {
        return bar() + x * z;
    };
}

공격자는 JS 컨텍스트에 대한 "실행" 권한이 없는 경우 "공용" 또는 "개인" 필드나 메서드에 액세스할 수 없습니다.공격자가 액세스 권한이 있는 경우 다음 한 줄을 실행할 수 있습니다.

eval("Foo = " + Foo.toString().replace(
    /{/, "{ this.eval = function(code) { return eval(code); }; "
));

위의 코드는 모든 컨스트럭터타입 프라이버시에 대해 일반적입니다.서 몇 가지 하지만, 은 이와 다른 수 .replace()파라미터를 지정합니다.

이 작업을 수행한 후 다음 명령을 사용하여 생성된 개체입니다.new Foo() 해서 '아까보다'가 나올 거예요.eval생성자의 폐쇄에 정의된 값 또는 메서드를 반환하거나 변경하기 위해 호출할 수 있는 메서드. §:

f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");

여기서 볼 수 있는 유일한 문제는 인스턴스가 1개만 있고 로드 시 생성된 경우에는 작동하지 않는다는 것입니다.그러나 실제로 프로토타입을 정의할 필요는 없으며 공격자가 동일한 매개 변수(예: 매개 변수들이 일정하거나 사용 가능한 값에서 계산됨)를 전달하기만 하면 생성자 대신 개체를 다시 생성할 수 있습니다.

내 생각에, 이것은 거의 Crockford의 해결책을 쓸모 없게 만든다.「프라이버시」는, 솔루션의 단점(가독성과 유지 보수성의 저하, 퍼포먼스의 저하, 메모리의 증가)을 쉽게 깨지기 때문에, 「프라이버시가 없는」프로토타입 베이스의 방법이 최적입니다.

는 보통 해서 표시를 합니다.__private ★★★★★★★★★★★★★★★★★」_protected메서드와 필드(Perl style)는 JavaScript에서 프라이버시를 갖는다는 생각은 그것이 얼마나 오해받는 언어인지를 보여줍니다.

그러므로 나는 크록포드의 첫 문장을 제외하고는 그의 의견 동의하지 않는다.

그럼 JS에서는 어떻게 진짜 프라이버시를 얻을 수 있을까요?서버 측에 프라이빗에 필요한 모든 것을 배치하고 JS를 사용하여 AJAX 콜을 실행합니다.

모듈 패턴의 정점:모듈 패턴 공개

매우 견고한 패턴으로 깔끔하고 작은 확장입니다.

퍼블릭 기능이 프라이빗 기능에 액세스 할 수 있는 모든 퍼블릭 및 프라이빗 기능을 필요로 하는 경우, 다음과 같은 오브젝트의 레이아웃 코드를 사용합니다.

function MyObject(arg1, arg2, ...) {
  //constructor code using constructor arguments...
  //create/access public variables as 
  // this.var1 = foo;

  //private variables

  var v1;
  var v2;

  //private functions
  function privateOne() {
  }

  function privateTwon() {
  }

  //public functions

  MyObject.prototype.publicOne = function () {
  };

  MyObject.prototype.publicTwo = function () {
  };
}
var TestClass = function( ) {

    var privateProperty = 42;

    function privateMethod( ) {
        alert( "privateMethod, " + privateProperty );
    }

    this.public = {
        constructor: TestClass,

        publicProperty: 88,
        publicMethod: function( ) {
            alert( "publicMethod" );
            privateMethod( );
        }
    };
};
TestClass.prototype = new TestClass( ).public;


var myTestClass = new TestClass( );

alert( myTestClass.publicProperty );
myTestClass.publicMethod( );

alert( myTestClass.privateMethod || "no privateMethod" );

Georgebrock과 비슷하지만 조금 덜 상세하게(IMHO) 이런 식으로 하는 데 문제가 있나요? (어디서도 본 적이 없습니다.)

편집: 모든 개별 인스턴스화에는 퍼블릭 메서드의 카피가 있기 때문에 프로토타입의 사용을 저해하기 때문에 이것은 다소 쓸모없다는 것을 깨달았습니다.

자바스크립트에서의 프라이빗/퍼블릭 메서드/멤버 및 인스턴스화에 대해 제가 지금까지 가장 즐겼던 것은 다음과 같습니다.

다음은 기사 http://www.sefol.com/?p=1090 입니다.

예를 들어 다음과 같습니다.

var Person = (function () {

    //Immediately returns an anonymous function which builds our modules 
    return function (name, location) {

        alert("createPerson called with " + name);

        var localPrivateVar = name;

        var localPublicVar = "A public variable";

        var localPublicFunction = function () {
            alert("PUBLIC Func called, private var is :" + localPrivateVar)
        };

        var localPrivateFunction = function () {
            alert("PRIVATE Func called ")
        };

        var setName = function (name) {

            localPrivateVar = name;

        }

        return {

            publicVar: localPublicVar,

            location: location,

            publicFunction: localPublicFunction,

            setName: setName

        }

    }
})();


//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");

//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");

//Prints "ben"
x.publicFunction();

//Prints "candide"
y.publicFunction();

//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");

//Shouldn't have changed this : prints "candide"
y.publicFunction();

//Should have changed this : prints "Ben 2"
x.publicFunction();

JSFiddle:http://jsfiddle.net/northkildonan/kopj3dt3/1/

대부분의 경우 모듈 패턴이 맞습니다.그러나 수천 개의 인스턴스가 있는 경우 클래스는 메모리를 절약합니다.메모리 절약이 문제이며 오브젝트에 소량의 개인 데이터가 포함되어 있지만 많은 공용 기능이 있는 경우 메모리를 절약하기 위해 모든 공용 기능을 .protype에 저장해야 합니다.

제가 생각해낸 건 다음과 같습니다.

var MyClass = (function () {
    var secret = {}; // You can only getPriv() if you know this
    function MyClass() {
        var that = this, priv = {
            foo: 0 // ... and other private values
        };
        that.getPriv = function (proof) {
            return (proof === secret) && priv;
        };
    }
    MyClass.prototype.inc = function () {
        var priv = this.getPriv(secret);
        priv.foo += 1;
        return priv.foo;
    };
    return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2

'''」priv에는 개인 속성이 포함되어 있습니다. 기능을 통해 할 수 .getPriv(), 이 는 반환됩니다.false하지 한secret주 폐쇄 내부에서만 알 수 있습니다.

이건 어때?

var Restaurant = (function() {

 var _id = 0;
 var privateVars = [];

 function Restaurant(name) {
     this.id = ++_id;
     this.name = name;
     privateVars[this.id] = {
         cooked: []
     };
 }

 Restaurant.prototype.cook = function (food) {
     privateVars[this.id].cooked.push(food);
 }

 return Restaurant;

})();

개인 변수 조회는 즉시 함수의 범위를 벗어나면 불가능합니다.기능이 중복되지 않아 메모리를 절약할 수 있습니다.

은 개인 입니다.privateVars[this.id].cooked타이핑하기엔 어처구니가 없다.이드

함수는 프라이빗에 부가됩니다.기능만 에 접속됩니다.windowobject : " :

(function(w,nameSpacePrivate){
     w.Person=function(name){
         this.name=name;   
         return this;
     };

     w.Person.prototype.profilePublic=function(){
          return nameSpacePrivate.profile.call(this);
     };  

     nameSpacePrivate.profile=function(){
       return 'My name is '+this.name;
     };

})(window,{});

사용방법:

  var abdennour=new Person('Abdennour');
  abdennour.profilePublic();

바이올린을 켜다

을 선호합니다.WeakMap이렇게 하면 공개 방법을 원래 있던 시제품에 유지할 수 있습니다.이것이 다수의 오브젝트에 대해 이 문제를 처리하는 가장 효율적인 방법인 것 같습니다.

const data = new WeakMap();

function Foo(value) {
    data.set(this, {value});
}

// public method accessing private value
Foo.prototype.accessValue = function() {
    return data.get(this).value;
}

// private 'method' accessing private value
function accessValue(foo) {
    return data.get(foo).value;
}

export {Foo};

2021년 여기!

이 폴리필은 개인 속성을 읽으려고 할 때 정의되지 않은 상태로 반환되는 개인 속성 및 메서드를 효과적으로 숨깁니다.이것에 의해, 프라이빗 메서드를 실행하려고 할 때, TypeError실제로 외부에 PRIVATE로 할 수 있습니다만, 퍼블릭메서드를 사용해 액세스 할 수 있습니다.

체크해 보면, 실장이 매우 간단함을 알 수 있습니다.Proxy 객체, 언더스코어 함수(_myprivate), getters, setters 등 대부분의 경우 별난 작업을 수행할 필요가 없습니다.그 중 아무것도.필요한 것은 퍼블릭인터페이스를 외부에 공개하는 것을 목적으로 하는 코드 조각과 같은 것을 컨스트럭터에 배치하는 것입니다.

((self) => ({
      pubProp: self.pubProp,
      // More public properties to export HERE
      // ...
      pubMethod: self.pubMethod.bind(self)
      // More public mehods to export HERE
      // Be sure bind each of them to self!!!
      // ... 
 }))(self);

위의 코드는 마법이 발생하는 지점입니다.IIFE는 최초로 인스턴스화된 객체의 컨텍스트에 바인드하여 노출하려는 속성 및 메서드만 포함하는 객체를 반환하는 것입니다.

숨겨진 속성과 메서드는 여전히 액세스할 수 있지만 OOP가 해야 하는 방식으로 공개 메서드를 통해서만 액세스할 수 있습니다.
코드의 그 부분을 module.exports로 간주합니다.

단, 이것은 언어에 최신 ES6 "#"을 추가하지 않은 것입니다.

'use strict';

class MyClass {
  constructor(pubProp) {
    let self = this;
    self.pubProp = pubProp;
    self.privProp = "I'm a private property!";
    return ((self) => ({
      pubProp: self.pubProp,
      // More public properties to export HERE
      // ...
      pubMethod: self.pubMethod.bind(self)
      // More public mehods to export HERE
      // Be sure to bind each of them to self!!!
      // ... 
    }))(self);
  }

  pubMethod() {
    console.log("I'm a public method!");
    console.log(this.pubProp);

    return this.privMethod();
  }

  privMethod() {
    console.log("I'm a private method!");
  return this.privProp
  }
}

const myObj = new MyClass("I'm a public property!");
console.log("***DUMPING MY NEW INSTANCE***");
console.dir(myObj);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC PROPERTIES***");
console.log(myObj.pubProp);
console.log("");
console.log("***TESTING ACCESS TO PRIVATE PROPERTIES***");
console.log(myObj.privProp);
console.log("");
console.log("***TESTING ACCESS TO PUBLIC METHODS***");
console.log("1. pubMethod access pubProp ");
console.log("2. pubMethod calls privMethod");
console.log("3. privMethod access privProp");
console.log("")
console.log(myObj.pubMethod());
console.log("");
console.log("***TESTING ACCESS TO PRIVATE METHODS***");
console.log(myObj.privMethod());

내 요지를 확인하다

개인 함수는 모듈 패턴을 사용하여 공용 변수에 액세스할 수 없습니다.

다들 자기 코드를 여기에 올렸으니까 나도 올릴 거야

나는 크록포드가 자바스크립트에서 실제 객체 지향 패턴을 소개했기 때문에 좋아한다.하지만 그는 또한 "그것"이라는 새로운 오해를 떠올렸다.

그럼 왜 "that = this"를 사용하는 걸까요?사적인 업무와는 전혀 관계가 없습니다.내적 기능과 관련이 있어!

Crockford에 따르면 이것은 버그 코드입니다.

Function Foo( ) {
    this.bar = 0; 
    var foobar=function( ) {
        alert(this.bar);
    }
} 

그래서 그는 이렇게 하자고 제안했다.

Function Foo( ) {
    this.bar = 0;
    that = this; 
    var foobar=function( ) {
        alert(that.bar);
    }
}

그래서 말씀드렸듯이 크록포드가 이것과 이것에 대한 설명을 잘못했다고 확신합니다(그러나 그의 코드는 확실히 옳습니다).아니면 누가 코드를 복사하는지 알기 위해 자바스크립트 세계를 속인 걸까요?나도 몰라...나는 브라우저 괴짜가 아니다.

편집

아, 그게 다구나.JavaScript에서 'var that = this;'는 무엇을 의미합니까?

그래서 크로키는 그의 설명이 정말 틀렸다.하지만 코드 그대로이기 때문에 그는 여전히 훌륭한 사람입니다. : )

일반적으로 개인 오브젝트를 오브젝트에 일시적으로 추가합니다.이 방법은 "전원 컨스트럭터"에서 프라이버시를 개방해야 합니다.프로토타입에서 메서드를 호출하면 프로토타입 메서드를 덮어쓸 수 있습니다.

  • "Power-Constructor"에서 공개 메서드에 액세스할 수 있도록 합니다. (ctx는 객체 컨텍스트입니다).

    ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
    
  • 이제 openPrivacy가 생겼습니다.

    GD.Fabric.openPrivacy = function(func, clss, ctx, _) {
        return function() {
            ctx._ = _;
            var res = clss[func].apply(ctx, arguments);
            ctx._ = null;
            return res;
        };
    };
    

내가 알아낸 건 이거야

여기서 찾을있는 한 등급의 설탕 코드가 필요합니다.보호, 상속, 가상, 정적 데이터도 지원합니다.

;( function class_Restaurant( namespace )
{
    'use strict';

    if( namespace[ "Restaurant" ] ) return    // protect against double inclusions

        namespace.Restaurant = Restaurant
    var Static               = TidBits.OoJs.setupClass( namespace, "Restaurant" )


    // constructor
    //
    function Restaurant()
    {
        this.toilets = 3

        this.Private( private_stuff )

        return this.Public( buy_food, use_restroom )
    }

    function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }

    function buy_food     (){ return "food"        }
    function use_restroom (){ this.private_stuff() }

})( window )


var chinese = new Restaurant

console.log( chinese.buy_food()      );  // output: food
console.log( chinese.use_restroom()  );  // output: There are 3 toilets available
console.log( chinese.toilets         );  // output: undefined
console.log( chinese.private_stuff() );  // output: undefined

// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
Class({  
    Namespace:ABC,  
    Name:"ClassL2",  
    Bases:[ABC.ClassTop],  
    Private:{  
        m_var:2  
    },  
    Protected:{  
        proval:2,  
        fight:Property(function(){  
            this.m_var--;  
            console.log("ClassL2::fight (m_var)" +this.m_var);  
        },[Property.Type.Virtual])  
    },  
    Public:{  
        Fight:function(){  
            console.log("ClassL2::Fight (m_var)"+this.m_var);  
            this.fight();  
        }  
    }  
});  

https://github.com/nooning/JSClass

https://github.com/TremayneChrist/ProtectJS 프로토타입에서 진정한 개인 메서드를 사용할 수 있는 새로운 도구를 만들었습니다.

예:

var MyObject = (function () {

  // Create the object
  function MyObject() {}

  // Add methods to the prototype
  MyObject.prototype = {

    // This is our public method
    public: function () {
      console.log('PUBLIC method has been called');
    },

    // This is our private method, using (_)
    _private: function () {
      console.log('PRIVATE method has been called');
    }
  }

  return protect(MyObject);

})();

// Create an instance of the object
var mo = new MyObject();

// Call its methods
mo.public(); // Pass
mo._private(); // Fail

실제 생성자 함수는 폐쇄해야 합니다. 여기서 개인 메서드를 정의할 수 있습니다.이러한 프라이빗 메서드를 사용하여 인스턴스의 데이터를 변경하려면 함수 인수 또는 .apply(this)를 사용하여 이 함수를 호출하여 "this"를 지정해야 합니다.

var Restaurant = (function(){
    var private_buy_food = function(that){
        that.data.soldFood = true;
    }
    var private_take_a_shit = function(){
        this.data.isdirty = true;   
    }
    // New Closure
    function restaurant()
    {
        this.data = {
            isdirty : false,
            soldFood: false,
        };
    }

    restaurant.prototype.buy_food = function()
    {
       private_buy_food(this);
    }
    restaurant.prototype.use_restroom = function()
    {
       private_take_a_shit.call(this);
    }
    return restaurant;
})()

// TEST:

var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);

조금 늦은 건 알지만 이건 어때요?

var obj = function(){
    var pr = "private";
    var prt = Object.getPrototypeOf(this);
    if(!prt.hasOwnProperty("showPrivate")){
        prt.showPrivate = function(){
            console.log(pr);
        }
    }    
}

var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));

언급URL : https://stackoverflow.com/questions/55611/javascript-private-methods

반응형