협의의 추상화, 즉 코드에서의 추상화는 관련된 비즈니스 로직을 속성과 메소드(동작)로 분리하는 것이며, 이러한 속성과 메소드가 객체를 형성할 수 있습니다.
이 추상화는 이해하기 어려운 코드를 강아지와 같은 물체와 같은 현실 세계와 관련된 개념으로 요약하기 위한 것입니다. 속성은 "털 색상", "품종", "나이", 등; 방법(행동)은 "짖는다", "달리기", "뼈를 물어뜯는다" 등으로 요약할 수 있다.
참고: 여기서 추상은 추상 클래스를 참조하지 않으며 캡슐화 섹션에서 추상 클래스에 대해 논의하는 것이 더 적절하다고 생각합니다.
Javascript에서 객체를 생성하는 방법은 다양하며 매우 간단합니다. 강아지 객체를 예로 들어보겠습니다.
1 var dog = { 2 hairColor: '白色', 3 breed: '贵宾', 4 age: 2, 5 shout: function() { 6 console.log('汪!汪!汪!'); //这里是你的业务逻辑代码,这里我就简单用这个来代替 7 }, 8 run: function() { 9 console.log('吃我灰吧,哈哈!');10 },11 gnawBone: function() {12 console.log('这是本狗最幸福的时候');13 }14 };
매우 편리합니다. 그런데 이때 질문이 있습니다. dog을 많이 만들고 싶으면 어떻게 해야 하나요? dog을 만들 때마다 var합니까?
그래서 이번에 클래스(class)라는 개념을 소개했습니다. 클래스는 동일한 특성을 가진 유사한 개체의 프로토타입이며 클래스 자체는 존재하지 않습니다. memory., 클래스의 코드를 실행하면 메모리에 객체(instance/instance)가 생성됩니다. 클래스는 객체를 생성하는 팩토리로 간단히 이해하면 됩니다.
Javascript(ES5)에는 클래스(class)가 없습니다. 생성자를 통해 클래스를 구현합니다.
1 /*类的创建*/ 2 function Dog() { 3 //构造函数:人们一致协定把构造函数的名字(即类名),首字母大写,以便区分 4 this.hairColor = '白色'; 5 /*this指向被创造的对象(实例),如果不明白可以简单的理解为给对象(this)赋予hairColor这个属性 6 */ 7 this.breed = '贵宾'; 8 this.age = 2; 9 this.runSpeed = null; //string10 /*属性的声明一定要放在构造函数的最顶部;11 有的属性可能一开始没有初始值,会在方法里才赋值,但你一定要在构造函数里声明一下12 有必要的话再声明一下属性的类型13 */14 }15 Dog.prototype.shout = function() {16 /*我们把方法追加到构造函数的prototype属性,而不是直接在构造函数里用this.shout = function(){};17 这样的好处是会让Dog创造的所有对象都共享一个方法,从而节约内存;18 一般来说属性在构造函数里赋予,方法在prototype里赋予;19 更多prototype的知识就看书去吧,这里不会深讲,作者要保持本章知识的封装性;20 */21 console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);22 //方法里通过this可以访问属性23 }24 Dog.prototype.run = function() {25 this.runSpeed = '10m/s';26 console.log('吃我灰吧,哈哈!本狗的速度可是有' + this.runSpeed);27 }28 Dog.prototype.gnawBone = function() {29 console.log('这是本狗最幸福的时候');30 }31 /*对象(实例)的创建与使用*/32 var dog1 = new Dog(); //33 console.log(dog1.breed); //log: '贵宾'34 dog1.shout(); //log: '汪!汪!汪!我是一只2岁的白色贵宾'35 var dog2 = new Dog(); //创建多只dog(对象/实例)36 var dog3 = new Dog();37 /*dog1、dog2、dog3这些对象的属性是各自的,但方法是共享的*/38 dog1.hairColor = '黑色'; //修改dog1的属性39 console.log(dog1.hairColor); //log: '黑色';dog1属性已被修改;40 console.log(dog2.hairColor); //'白色';其它对象不受影响;41 console.log(dog3.hairColor); //log: '白色'42 console.log(dog1.shout === dog2.shout); //log: true;dog1的shout方法和dog2的是同一个方法;
하지만 다시 새로운 질문이 있습니다. 여기 온다: 갈색 테디를 만들고 싶은데 어떻게 해야 하나요? 이 문제는 클래스 생성 시 클래스 생성자에 매개변수를 전달하여 해결할 수 있습니다.
앞서 말한 것처럼 클래스가 생성한 각 객체(인스턴스)의 메소드는 공유되고, 속성도 각자의 것이지만, 공유 속성만 만들고 싶다면 어떻게 해야 할까요? 예를 들어, 프로그램의 개 개체(인스턴스) 수를 기록하기 위해 instanceNumber 속성을 만들고 싶습니다.
이때 Dog 클래스에 정적 속성을 생성할 수 있습니다. 정적 속성은 클래스에 속하므로 객체(인스턴스) 변경에 따라 변경되지 않으며 전역 변수를 설정하는 데 사용할 수 있습니다. 클래스의 전역 매개변수 구성입니다.
다음은 새로운 코드입니다:
1 function Dog(hairColor, breed, age) { 2 this.hairColor = hairColor; //string,这种依赖参数的属性最好声明下类型或接口; 3 this.breed = breed; //string 4 this.age = age; //number 5 this.runSpeed = null; //string 6 Dog.instanceNumber++; 7 } 8 Dog.instanceNumber = 0; //创建静态属性 9 Dog.prototype.shout = function() {10 console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);11 }12 Dog.prototype.run = function() {13 this.runSpeed = '10m/s';14 console.log('吃我灰吧,哈哈!本狗的速度可是有' + this.runSpeed);15 }16 Dog.prototype.gnawBone = function() {17 console.log('这是本狗最幸福的时候');18 }19 Dog.prototype.getInstanceNumber = function() { //为访问静态属性封装方法20 return Dog.instanceNumber;21 }22 var dog1 = new Dog('白色', '贵宾', 2);23 console.log(Dog.instanceNumber); //log: 1;虽然可以这样访问静态属性,并且还可以修改它,但坚决不推荐这样做24 console.log(dog1.getInstanceNumber()); //log: 1;正确的做法!为什么要这样做,在封装一节会详细讲25 var dog2 = new Dog('棕色', '泰迪', 1);26 console.log(dog1.getInstanceNumber()); //log: 2;27 var dog3 = new Dog('黑色', '土狗', 3);28 console.log(dog1.getInstanceNumber()); //log: 3;29 dog1.shout(); //log: '汪!汪!汪!我是一只2岁的白色贵宾'30 dog2.shout(); //log: '汪!汪!汪!我是一只1岁的棕色泰迪'31 dog3.shout(); //log: '汪!汪!汪!我是一只3岁的黑色土狗'
다음은 ES6 클래스의 생성 방법입니다. 이 코드는 아래 TypeScript 코드를 포함하여 Chrome 브라우저에서 직접 실행할 수 있습니다. .
1 class Dog { 2 constructor(hairColor, breed, age) { //代表这个类的构造函数 3 this.hairColor = hairColor; //string 4 this.breed = breed; //string 5 this.age = age; //number 6 this.runSpeed = null; //string 7 Dog.instanceNumber++; 8 } 9 shout() {10 console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);11 }12 run() {13 this.runSpeed = '10m/s';14 console.log('吃我灰吧,哈哈!本狗的速度可是有' + this.runSpeed);15 }16 gnawBone() {17 console.log('这是本狗最幸福的时候');18 }19 getInstanceNumber() {20 return Dog.instanceNumber;21 }22 }//ES6类的创建就比较舒服了,class把整个类用{}包裹在一起,写法也比较方便。23 Dog.instanceNumber = 0;//遗憾的是ES6里也没有规范静态属性,还是跟ES5一样的用法,据说ES7已有一个静态属性的提案24 let dog1 = new Dog('白色', '贵宾', 2);25 let dog2 = new Dog('棕色', '泰迪', 1);26 let dog3 = new Dog('黑色', '土狗', 3);27 dog1.shout(); //log: '汪!汪!汪!我是一只2岁的白色贵宾'28 dog2.shout(); //log: '汪!汪!汪!我是一只1岁的棕色泰迪'29 dog3.shout(); //log: '汪!汪!汪!我是一只3岁的黑色土狗'30 console.log(dog1.getInstanceNumber()); //log: 3;
TypeScript는 객체를 생성합니다. TypeScript에도 유용한 기능이 많이 있지만 이 장에서는 더 자세히 소개하기가 불편합니다.
上面的例子是我们明确知道要创建一个对象(实例)dog,但实际开发当中是没有人告诉我们需要创建哪些对象的,领导给我们的只有需求,所以我们要分析需求的业务逻辑,把需求分解成一个个对象。
比如说现在领导给我们一个需求:做一个超市收银系统,分为两种角色:收银员和管理员,收银员可以查询物品信息、统计价格、录入账单信息、打印小票,管理员可以查看账单信息、统计账单信息。
注意需求中的名词:收银员、管理员、物品信息、账单、小票,这些就是天然的对象,这是最初步的抽象。
让我们再注意动词:查询、统计、录入、打印,我们是不是也可以抽象成对象?查询器?统计器?
然后我们开始coding吧,不要纠结自己的抽象是否完美,作者很赞同Facebook的一句标语:Done is better than perfect(比完美更重要的是完成).
当某个对象的代码不断膨胀,慢慢超出控制的时候(作者自己的的标准是一个对象尽量不超过300行代码),这时候你就得考虑更深层次的抽象了,查找这个对象里代码比较多的属性、方法、然后抽象成另一个对象,把新对象作为原先对象的成员(属性)。
function Dog(){ this._tail = new Tail();//把尾巴tail抽象成另一个对象,作为dog的一个属性; }
当然,你成了老司机后可以一开始就把一个对象再抽象出许多成员对象,随你喜欢。
如果你喜欢作者的文章,记得收藏,你的点赞是对作者最大的鼓励;
作者会尽量每周更新一章,下一章是讲继承;
大家有什么疑问可以留言或私信作者,作者尽量第一时间回复大家;
如果老司机们觉得那里可以有不恰当的,或可以表达的更好的,欢迎指出来,作者会尽快修正、完善。
위 내용은 JavaScript의 추상화에 대한 자세한 설명(ES5, ES6, TypeScript 데모)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!