[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_foodand 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는 프로토 타입을 사용하며 객체 지향 언어와 같은 클래스 (또는 해당 문제에 대한 메소드)가 없습니다. JavaScript 개발자는 JavaScript로 생각해야합니다.

Wikipedia 인용문 :

많은 객체 지향 언어와 달리 함수 정의와 메소드 정의는 구별되지 않습니다. 오히려, 함수 호출 중에 구별이 발생합니다. 함수가 객체의 메소드로 호출되면 함수의 로컬 this 키워드는 해당 호출을 위해 해당 객체에 바인딩됩니다.

자체 호출 기능호출 기능 을 사용하여 개인 “방법”을 호출하는 솔루션 :

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 를 사용 하는 경우 모듈 로딩 시스템 을 활용할 수 있으므로 IIFE 가 필요하지 않습니다 .

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

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

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

exports.MyObject = MyObject;

파일을로드하십시오.

var MyObject = require('./MyObject').MyObject;

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

바인드 연산자가있는 (실험) ES7

바인드 연산자 ::는 ECMAScript 제안 이며 Babel ( 스테이지 0 ) 에서 구현됩니다 .

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

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

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

파일을로드하십시오.

import MyObject from './MyObject';

let myObject = new MyObject('bar');
myObject.publicFun();      // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function


답변

다음과 같은 개인용 메소드를 시뮬레이션 할 수 있습니다.

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://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html)를 참조 하십시오.


답변

공개 API가 있고 개인 및 공개 메소드 / 속성을 원할 때 이러한 상황에서는 항상 모듈 패턴을 사용합니다. 이 패턴은 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


답변

다음은 Douglas Crockford가 자신의 사이트 에서 JavaScript로 제안한 내용을 이해하기 위해 만든 클래스입니다.

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

}


답변

나는 이것을 혼란스럽게했다 : 편집 : 실제로 누군가가 동일한 솔루션에 연결했습니다. 어이!

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!'


답변

클로저에 대한 이해 부족으로 인해 이러한 질문이 반복해서 발생한다고 생각합니다. Сlosures는 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')

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