JavaScript의 캡슐화
캡슐화는 단순히 외부 세계가 객체의 공통 변수와 기능에만 액세스할 수 있고 세부 사항과 데이터를 숨길 수 있음을 의미합니다.
js에서 객체를 생성하는 방법에는 문을 여는 방법, 명명 규칙을 사용하여 개인 변수를 구별하는 방법, 클로저를 사용하여 실제 개인 변수를 만드는 세 가지 방법이 있습니다.
1. 오픈 도어는 객체를 구현하는 가장 기본적인 방법이며, 모든 메소드와 변수는 공통적이고 외부에서 접근 가능합니다.
var Book = function(name){ if(this.check(name)){ console.log("error"); throw new Error("name null"); } this.name = name; } Book.prototype = { check:function(name){ if(!name){ return true; } }, getName:function(){ return this.name; } } var book = new Book("哈哈"); //output:哈哈 哈哈 console.log(book.name,book.getName());
이 예시는 외부 세계가 객체의 속성과 메소드에 직접 접근할 수 있는 열린 문(open door)의 전형적인 예입니다. "this"를 사용하여 속성과 변수가 생성되는 것을 확인할 수 있습니다.
2. 개인 변수를 구별하기 위해 명명 규칙을 사용하십시오. 이 메소드는 프로그래머가 _getName() 메소드를 사용하려는 경우에는 개방형 메소드의 최적화된 버전입니다. 메소드를 호출하는 것은 여전히 방지할 수 없으며 실제로 변수를 숨기는 것은 아닙니다.
3. 클로저는 실제 비공개 변수를 생성합니다. 이 방법은 js의 함수에만 범위가 있다는 점을 활용하고 생성자의 범위에서 관련 변수를 정의합니다. 이러한 변수는 정의 도메인 범위의 모든 함수에서 액세스할 수 있습니다.
var Book2 = function(name){ if(check(name)){ console.log("error"); throw new Error("name null"); } name = name; function check(name){ if(!name){ return true; } } this.getName = function(){ return name; } } Book2.prototype = { display:function(){ //无法直接访问name return "display:"+this.getName(); } } var book2 = new Book2("哈哈"); //output:undefined "哈哈" "display:哈哈" console.log(book2.name,book2.getName(),book2.display());
보시다시피 이 예에서는 name에 직접 액세스하면 정의되지 않은 결과가 반환됩니다. open-door 유형의 변수는 "this"를 사용하여 생성되는 반면, 이 예에서는 var를 사용하여 변수를 생성하는 것과 차이점을 알 수 있습니다. 따라서 name 및 check 함수는 생성자에서만 생성할 수 있으며 함수 범위 내에서 액세스할 수 있으며 외부 세계에서는 직접 액세스할 수 없습니다.
이 방법은 처음 두 가지 방법의 문제를 해결하지만 특정 단점도 있습니다. 개방형 객체 생성 모드에서는 모든 메서드가 프로토타입 객체에서 생성되므로 생성된 객체 인스턴스 수에 관계없이 이러한 메서드의 복사본이 메모리에 하나만 존재합니다. 이 메서드를 사용하면 생성된 각 새 객체가 생성됩니다. 더 많은 메모리를 소비하는 개인 변수 및 메소드의 새로운 복사본.
자바스크립트의 상속
도서 기반 수업:
var Book = function(name){ if(this.check(name)){ console.log("error"); throw new Error("name null"); } this.name = name; } Book.prototype = { check:function(name){ if(!name){ return true; } }, getName:function(){ return this.name; } }
상속된 메서드:
function extend(subClz,superClz){ var F = function(){} F.prototype = superClz.prototype; subClz.prototype = new F(); subClz.prototype.constructor = subClz; subClz.superClass = superClz.prototype; if(superClz.prototype.constructor == Object.prototype.constructor){ superClz.prototype.constructor = superClz; }
빈 함수 F를 브리지로 사용하면 부모 클래스를 직접 인스턴스화할 때 부모 클래스 생성자를 호출하는 추가 오버헤드를 피할 수 있습니다. 또한 부모 클래스의 생성자에 매개 변수가 있는 경우 subClass.prototype = new superClass()를 통해 직접 구현하려고 합니다. ; 상위 클래스 생성자를 호출하고 프로토타입 체인을 통한 상속은 허용되지 않습니다.
subClz.superClass = superClz.prototype; if(superClz.prototype.constructor == Object.prototype.constructor){ superClz.prototype.constructor = superClz; }
이 세 문장을 추가하면 하위 클래스가 상위 클래스를 상속하고 Book.call(this, name)을 작성하는 것을 방지할 수 있습니다. 대신 ArtBook.superClass.Constructor.call(this, name)을 작성하면 됩니다.
그리고 하위 클래스가 상위 클래스 메서드를 재정의하면 상위 클래스 메서드를 호출할 수 있습니다.
ArtBook.prototype.getName = functiion(){ return ArtBook.superClass.getName.call(this) + "!!!"; }
ArtBook 하위 클래스:
var ArtBook = function(name,price){ ArtBook.superClass.Constructor.call(this,name); this.price = price; } extend(ArtBook,Book); ArtBook.prototype.getPrice = function(){ return this.price; } ArtBook.prototype.getName = function(){ return ArtBook.superClass.getName.call(this)+"!!!"; }