2016-07-07 23 views
3

ES5에서 "클래스"가 작동하는 방식과 Java와 같은 일반적인 형식 지정 객체 지향 언어에 대한 지식을 자바 스크립트에 적용하는 방법을 이해하려고합니다.javascript의 클래스 및 '액세스 한정자'

다음 코드 샘플에서는 내 질문에 주석을 달았습니다.

var MyClass = (function() { 

    // [What am I?] A private variable? 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

나는 "개인적인"것에 대해 대부분 궁금해합니다. 마찬가지로이 클래스의 인스턴스가 여러 개인 경우 어떻게됩니까? 서로 개인적인 변수와 기능을 방해 할 수 있습니까?

+1

'어떻게 Java와 같은 전통적인 형식화 된 객체 지향 언어에 대한 지식을 자바 스크립트에 적용 할 수 있습니까? 자바 스크립트는 다른 것처럼 조용 할 수 없습니다. 다른 사고 방식이 필요합니다. JS에는 "클래스"가 없으며 (ES2015가있는 것처럼 여기는 경우에도) "클래스"로 알려진 것은 모든 인스턴스간에 속성 및 메서드를 공유 할 수있는 호출 가능한 동적 개체 (생성자 함수)입니다. 객체의 프로토 타입이 변경되면 모든 인스턴스가 영향을받습니다. –

답변

4

는 우선이 조금 해결합니다 :

을 ... 그리고 어떻게 자바 스크립트 자바와 같은 전통적인 입력 객체 지향 언어의 내 지식을 적용 할 수 있습니다.

당신은 자주있는 멀리 자바 스크립트의 사고로 얻을 수있는 Java/C#을/당신이 경우에 자바 스크립트 하지 같은 때문에 등.하지만, A는) 그것은, 어떤 시점에서 당신을 물린 것 같은 비트 Java/C#/etc., 비슷하게 보일 수있는 장식이 있지만 은 근본적으로입니다. B) 근본적으로 다른 성격을 사용하는 방법을 알지 못해 JavaScript의 진정한 힘을 놓칠 수 있습니다. (어떻게 알 수 있습니까? 나는 정확히, 자바 [심지어 C++] 배경에서 나온 자바 스크립트가 비슷 가정이 있었다.) 원격으로 비판의 형태로 의미가 아니에요

, 그것은 단지 단어의 슬기로운. 자바 스크립트의 프로토 타입 상속과 클로저가 어떻게 작동하는지 자세히 배우십시오. 문제를 해결하는 방법은 Java/C#/등에서 사용하는 방법과 약간 다릅니다.

답변 인라인 : 나는 주로 "개인"물건에 대해 궁금

var MyClass = (function() { 

    // [What am I?] A private variable? 
    // ==> A private *class* variable (static variable). Not instance-specific. 
    var myVariable1 

    // Constructor. 
    function MyClass() { 
     // Essentially a public variable. 
     // ==> A public field/property/variable, choose your terminology. :-) 
     // ==> The Java spec calls them both fields and variables (oddly). 
     // ==> In JavaScript, they're called properties. 
     this.myVariable2 = 0; 
    } 

    // Public method returning myVariable1. 
    // ==> Correct, but note that myVariable1 is shared across all instances 
    MyClass.prototype.myMethod1 = function() { 
     return myVariable1; 
    }; 

    // Public method returning public variable. 
    // ==> Yes, note that this one is returning an instance-specific field/property/variable 
    MyClass.prototype.myMethod2 = function() { 
     return this.myVariable2; 
    }; 

    // [What am I?] A private method? 
    // ==> A private *class* method (static method), yes. 
    function myMethod3() { 
     return 0; 
    } 

    return MyClass; 

}()); 

. 마찬가지로이 클래스의 인스턴스가 여러 개인 경우 어떻게됩니까? 서로 개인적인 변수와 기능을 방해 할 수 있습니까?

예, 내가 언급 한 바와 같이, 그들은 수업 전반입니다. private "instance field"를 원한다면 생성자 내에서 선언해야하며 생성자 내에서 액세스 할 수 있도록 모든 함수를 작성해야합니다.

function MyClass(arg) { 
    var privateInstanceInfo = arg; // We could also just use arg directly 

    this.accessThePrivateInstanceInfo = function() { 
     return privateInstanceInfo * 42; 
    }; 
} 
MyClass.prototype.useOnlyPublicInfo = function() { 
    // This cannot access `privateInstanceInfo` directly. 
    // It *can* access the function `accessThePrivateInstanceInfo` 
    // because that's public: 
    return accessThePrivateInstanceInfo(); 
}; 
var c = new MyClass(2); 
console.log(c.useOnlyPublicInfo()); // 84 

이 모든이 질문과 답변에 자세히 설명되어 있습니다 폐쇄라는 개념 아래로 : How do JavaScript closures work? 나는 또한 몇 년 전에 Closures are not complicated에서 내 기사를 참조 할 것, 사물에 대한 일부 오래된 용어를 사용하면서 최신 사양과 비교해도 여전히 개념을 잘 설명합니다.

래퍼로 사용한 인라인 호출 함수 (IIFE)는 그 안에있는 모든 함수가 닫히는 단일 실행 컨텍스트를 만듭니다. 즉, 함수가 반환 된 후에도 해당 컨텍스트 내에서 정의 된 변수와 함수에 실시간으로 액세스 할 수 있습니다. 한 번만 호출하기 때문에 하나의 컨텍스트가 있으므로 myVariable1myMethod3 중 하나만 있습니다.개인 예를 정보를 생성 내 예에서

, 우리는 새로운 문맥 의 생성자를 호출 할 때마다을 만든 사실을 사용합니다. 이 컨텍스트는 다른 것과 공유되지 않으므로 인스턴스와 관련됩니다.

function makeRandomName() { 
    var str = ""; 
    while (str.length < 10) { 
     str += String.fromCharCode(32 + Math.floor(95 * Math.random())); 
    } 
    return "__" + str; 
} 
var MyClass = (function() { 
    var pseudoPrivatePropName = makeRandomName(); 

    function MyClass() { 
     this[pseudoPrivatePropName] = 42; 
    } 

    // .... 

    return MyClass; 
})(); 

가 인생 내부의 코드는 이름을 알고 :

는 무작위로 선택된 이름을 사용하는 것입니다 생성자에서 함수를 정의 할 필요없이 - 개인 인스턴스 속성 근처 을 얻을 수있는 방법있다 속성의 외부 코드는 그렇지 않습니다. 이제 악의적 인 코드가 여전히이 속성을 찾을 수 있지만, 특히 둘 이상이 있으면 훨씬 더 어려워집니다. (둘 이상이있는 경우, 당신은 위의 것보다 더 좋은 이름 할당이 필요합니다.) ES2015 (ES6)에서

대신 이름 할당이있는의 ...

var pseudoPrivatePropName = Symbol(); 

를 사용할 수 있습니다.

내 블로그에 this somewhat-outdated article 세부 사항.

+1

정교한 답변을 해주셔서 감사합니다! – datcat