>  기사  >  웹 프론트엔드  >  객체 지향 JavaScript에 대한 쉬운 소개

객체 지향 JavaScript에 대한 쉬운 소개

巴扎黑
巴扎黑원래의
2017-06-26 11:52:471098검색

 이 장에서는 모든 사람이 저자의 이전 기사를 읽었다고 가정합니다. "JavaScriptEasy Introduction to Object-Oriented Abstraction"

왜 캡슐화하나요?

  캡슐화는 객체의 내부 속성과 메서드를 숨기는 것입니다. 외부 코드는 특정 인터페이스를 통해서만 객체에 액세스할 수 있습니다. 이 역시 인터페이스 지향 프로그래밍 아이디어의 일부입니다.

  캡슐화는 객체지향 프로그래밍에서 매우 중요한 부분입니다. 캡슐화가 없는 코드는 어떤 모습인지 살펴보겠습니다.

1     function Dog(){2         this.hairColor = '白色';//string3         this.breed = '贵宾';//string4         this.age = 2;//number5     }6     var dog = new Dog();7     console.log(dog.breed);//log: '贵宾'

  문제 없을 것 같지만 breed 속성 이름이 수정됐는데 어떻게 해야하나요? 예를 들어 this.type = 'VIP', 으로 변경하면 Dog 클래스를 사용하는 모든 코드를 변경해야 합니다.

 클래스용 코드와 클래스 사용용 코드를 모두 작성하고 이 클래스를 사용하는 곳이 많지 않다면 이렇게 작성해도 상관없습니다.

 그러나 이 클래스가 여러 곳에서 사용되거나 공동 개발 중에 다른 사람들도 귀하의 클래스를 사용하는 경우 올바른 접근 방식은 다음과 같습니다:

 1     function Dog(){ 2         this.hairColor = '白色';//string 3         this.age = 2;//number 4         this._breed = '贵宾';//string 5     } 6     Dog.prototype.getBreed = function(){ 7         return this._breed; 8     } 9     Dog.prototype.setBreed = function(val){10         this._breed = val;11     }12     var dog = new Dog();13     console.log(dog.getBreed());//log: '贵宾'14     dog.setBreed('土狗');

 getBreed( ) 내부 속성이 변경되는 경우(예: breedtype 로 대체되면 getBreed()에서 코드만 변경하면 되며 이 속성 작업의 모든 획득을 모니터링할 수 있습니다. .

따라서 캡슐화에는 많은 이점이 있습니다.

1. 인터페이스가 변경되지 않는 한 내부 구현은 마음대로 변경할 수 있습니다.

2. 내부 구현이 어떻게 되든 사용자가 사용하기 매우 편리합니다. 3. 코드 결합을 줄입니다.

 4. 대규모 애플리케이션 및 다중 사용자 공동 개발 요구 사항을 충족하려면

getter

/setter

를 사용하여 개인 속성을 캡슐화하세요. 실제로 속성을 캡슐화하는 또 다른 방법이 있습니다. 즉, 아래와 같이 getter/setter를 사용하는 것입니다. demo, 이 장에서는 원리에 대해 설명하지 않고 사용법에 대해서만 설명합니다. 원리는 다음에서 확인할 수 있습니다. yourself:

 1     function Dog(){ 2         this.hairColor = '白色';//string 3         this.age = 2;//number 4         this._breed = '贵宾';//string 5         Object.defineProperty(this, 'breed', {//传入this和属性名 6             get : function () { 7                 console.log('监听到了有人调用这个get breed') 8                 return this._breed; 9             },10             set : function (val) {11                 this._breed = val;12                 /*13                 如果不设置setter的话默认这个属性是不可设置的14                 但有点让人诟病的是,浏览器并不会报错15                 所以即使你想让breed是只读的,你也应该设置一个setter让其抛出错误:16                 throw 'attribute "breed"  is read only!';17                 */18             }19         });20     }21     var dog = new Dog();22     console.log(dog.breed);23     /*log:24         '监听到了有人调用这个get breed接口'25         '贵宾'26     */27     dog.breed = '土狗';28     console.log(dog.breed);29     /*log:30         '监听到了有人调用这个get breed接口'31         '土狗'32     */
하지만 이 방법은 작성하기가 더 번거롭고 작성자는 일반적으로 getBreed() 메서드를 사용하며,
getter

/setter

는 일반적으로

readonly 속성에 사용되며 더 중요한 인터페이스와 캡슐화된 인터페이스 없이 속성 작업을 재구성하는 것입니다. 클로저를 사용하여 개인 속성을 캡슐화할 수도 있는데, 이는 가장 안전하지만 추가 메모리 오버헤드를 발생시키므로 작성자는 이를 별로 사용하는 것을 좋아하지 않습니다. Public/

Private 개념

처음 두 섹션에서는 캡슐화를 간략하게 이해했지만 이것만으로는 충분하지 않습니다. 먼저 다음 개념을 이해해 보겠습니다. Private 속성 : 즉, 속성입니다. 클래스 내에서만 접근 및 수정이 가능하며, 외부 접근은 허용되지 않습니다.

 Private 메소드

: 클래스 내에서만 호출이 가능한 메소드로, 외부 호출은 금지됩니다.

 공용 속성: 클래스 외부에서 얻고 수정할 수 있는 속성입니다. 이론적으로 클래스의 모든 속성은 비공개 속성이어야 하며 캡슐화된 인터페이스를 통해서만 액세스할 수 있습니다. 그러나 일부 작은 클래스나 덜 자주 사용되는 클래스의 경우 인터페이스를 캡슐화하는 것이 더 편리하다면 필요하지 않습니다.

공개 메소드

: 외부에서 호출할 수 있는 메소드

getBreed()와 같은 인터페이스를 구현하는 메소드는 공개 메소드이자 외부에 노출되는 동작 메소드입니다.

 정적 속성, 정적 메서드: 클래스 자체의 속성 및 메서드. 공개와 비공개를 구분할 필요가 없습니다. 모든 정적 속성과 정적 메서드는 비공개여야 하며 캡슐화된 인터페이스를 통해 액세스해야 합니다. 이것이 바로 이전 장에서 작성자가 Dog에 액세스하기 위해 getInstanceNumber()

를 사용한 이유입니다. 인스턴스번호

속성. ES5 데모는 다음과 같습니다:

 1     function Dog(){ 2         /*公有属性*/ 3         this.hairColor = null;//string 4         this.age = null;//number 5         /*私有属性,人们共同约定私有属性、私有方法前面加上_以便区分*/ 6         this._breed = null;//string 7         this._init(); 8         /*属性的初始化最好放一个私有方法里,构造函数最好只用来声明类的属性和调用方法*/ 9         Dog.instanceNumber++;10     }11     /*静态属性*/12     Dog.instanceNumber = 0;13     /*私有方法,只能类的内部调用*/14     Dog.prototype._init = function(){15         this.hairColor = '白色';16         this.age = 2;17         this._breed = '贵宾';18     }19     /*公有方法:获取属性的接口方法*/20     Dog.prototype.getBreed = function(){21         console.log('监听到了有人调用这个getBreed()接口')22         return this._breed;23     }24     /*公有方法:设置属性的接口方法*/25     Dog.prototype.setBreed = function(breed){26         this._breed = breed;27         return this;28         /*这是一个小技巧,可以链式调用方法,只要公有方法没有返回值都建议返回this*/29     }30     /*公有方法:对外暴露的行为方法*/31     Dog.prototype.gnawBone = function() {32         console.log('这是本狗最幸福的时候');33         return this;34     }35     /*公有方法:对外暴露的静态属性获取方法*/36     Dog.prototype.getInstanceNumber = function() {37         return Dog.instanceNumber;//也可以this.constructor.instanceNumber38     }39     var dog = new Dog();40     console.log(dog.getBreed());41     /*log:42         '监听到了有人调用这个getBreed()接口'43         '贵宾'44     */45     /*链式调用,由于getBreed()不是返回this,所以getBreed()后面就不可以链式调用了*/46     var dogBreed = dog.setBreed('土狗').gnawBone().getBreed();47     /*log:48         '这是本狗最幸福的时候'49         '监听到了有人调用这个getBreed()接口'50     */51     console.log(dogBreed);//log: '土狗'52     console.log(dog);

  ES6 데모 (초보자는 ES6 및 TypeScrpt 구현 부분을 읽지 마세요):

 1     class Dog{ 2         constructor(){ 3             this.hairColor = null;//string 4             this.age = null;//number 5             this._breed = null;//string 6             this._init(); 7             Dog.instanceNumber++; 8         } 9         _init(){10             this.hairColor = '白色';11             this.age = 2;12             this._breed = '贵宾';13         }14         get breed(){15             /*其实就是通过getter实现的,只是ES6写起来更简洁*/16             console.log('监听到了有人调用这个get breed接口');17             return this._breed;18         }19         set breed(breed){20             /*跟ES5一样,如果不设置的话默认breed无法被修改,而且不会报错*/21             console.log('监听到了有人调用这个set breed接口');22             this._breed = breed;23             return this;24         }25         gnawBone() {26             console.log('这是本狗最幸福的时候');27             return this;28         }29         getInstanceNumber() {30             return Dog.instanceNumber;31         }32     }33     Dog.instanceNumber = 0;34     var dog = new Dog();35     console.log(dog.breed);36     /*log:37         '监听到了有人调用这个get breed接口'38         '贵宾'39     */40     dog.breed = '土狗';//log:'监听到了有人调用这个set breed接口'41     console.log(dog.breed);42     /*log:43         '监听到了有人调用这个get breed接口'44         '土狗'45     */

 

  ES5ES6中虽然我们把私有属性和方法用“_”放在名字前面以区分,但外部还是可以访问到属性和方法的。

  TypeScrpt中就比较规范了,可以声明私有属性,私有方法,并且外部是无法访问私有属性、私有方法的:

 

 1     class Dog{ 2         public hairColor: string; 3         readonly age: number;//可声明只读属性 4         private _breed: string;//虽然声明了private,但还是建议属性名加_以区分 5         static instanceNumber: number = 0;//静态属性 6         constructor(){ 7             this._init(); 8             Dog.instanceNumber++; 9         }10         private _init(){11             this.hairColor = '白色';12             this.age = 2;13             this._breed = '贵宾';14         }15         get breed(){16             console.log('监听到了有人调用这个get breed接口');17             return this._breed;18         }19         set breed(breed){20             console.log('监听到了有人调用这个set breed接口');21             this._breed = breed;22         }23         public gnawBone() {24             console.log('这是本狗最幸福的时候');25             return this;26         }27         public getInstanceNumber() {28             return Dog.instanceNumber;29         }30     }31     let dog = new Dog();32     console.log(dog.breed);33     /*log:34         '监听到了有人调用这个get breed接口'35         '贵宾'36     */37     dog.breed = '土狗';//log:'监听到了有人调用这个set breed接口'38     console.log(dog.breed);39     /*log:40         '监听到了有人调用这个get breed接口'41         '土狗'42     */43     console.log(dog._breed);//报错,无法通过编译44     dog._init();//报错,无法通过编译

 

注意事项:

  1、暴露给别人的类,多个类组合成一个类时,所有属性一定都要封装起来;

  2、如果你来不及封装属性,可以后期用getter/setter弥补;

  3、每个公有方法,最好注释一下含义;

  4、在重要的类前面最好用注释描述所有的公有方法;

后话

  如果你喜欢作者的文章,记得收藏,你的点赞是对作者最大的鼓励;

  作者会尽量每周更新一章,下一章是讲继承;

  大家有什么疑问可以留言或私信作者,作者尽量第一时间回复大家;

  如果老司机们觉得那里可以有不恰当的,或可以表达的更好的,欢迎指出来,我会尽快修正、完善。

 

위 내용은 객체 지향 JavaScript에 대한 쉬운 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.