Maison  >  Article  >  interface Web  >  Explication détaillée de l'abstraction en JavaScript (démo par ES5, ES6, TypeScript)

Explication détaillée de l'abstraction en JavaScript (démo par ES5, ES6, TypeScript)

零下一度
零下一度original
2017-06-26 10:23:231705parcourir

Le concept d'abstraction

L'abstraction au sens étroit, c'est-à-dire l'abstraction dans le code, consiste à séparer une logique métier associée en attributs et méthodes (comportement). et les méthodes peuvent former un objet.

Cette abstraction consiste à résumer le code difficile à comprendre en concepts liés au monde réel, comme un objet comme un chiot : les attributs peuvent être résumés comme "couleur du pelage", « race », « âge », etc. ; les méthodes (comportements) peuvent être résumées comme « aboyer », « courir », « ronger les os », etc.

Remarque  : Le résumé ici ne fait pas référence aux classes abstraites. Je pense qu'il est plus approprié de discuter des classes abstraites dans la section encapsulation.

Concept et implémentation de la classe

Il existe de nombreuses façons de créer un objet en Javascript, et c'est très simple Prenons l'objet chiot comme exemple. :

 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 };

C'est très pratique, mais il y a un problème en ce moment : Que dois-je faire si je veux créer beaucoup de chien ? Est-ce que je var à chaque fois que je crée un chien ?

C'est donc à cette époque que nous avons introduit le concept de classe (class). Une classe est un prototype d'objets similaires ayant les mêmes caractéristiques. Objet (instance), la classe elle-même n'existe pas dans la mémoire. Lorsque le code de la classe est exécuté, un objet (instance/instance) est créé dans la mémoire. peut être simplement Comprendre les classes comme des usines qui créent des objets.

Il n'y a pas de classe (class) en Javascript (ES5), il Les classes sont implémentées via des constructeurs :

 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的是同一个方法;

Mais un nouveau problème revient : je veux créer Que faire avec une peluche marron ? Ce problème peut être résolu en passant des paramètres au constructeur de la classe lors de sa création.
Comme mentionné dans le cas précédent, les méthodes de chaque objet (instance) créé par la classe sont partagées, et les attributs sont les leurs, mais que dois-je faire si je souhaite simplement créer un attribut partagé ? Par exemple, je souhaite créer un attribut instanceNumber pour enregistrer le nombre d'objets chien (instances) dans le programme.

À ce stade, vous pouvez créer un attribut statique pour la classe Dog. L'attribut statique appartient à la classe, il ne changera donc pas avec le changement de l'objet (instance). Il peut être utilisé pour définir. les variables globales de la classe, la configuration des paramètres globaux, etc.

Voici le nouveau code :

 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岁的黑色土狗'

Vient ensuite la méthode de création de la classe ES6. Ce code peut être exécuté directement dans le navigateur Chrome. vous n'en avez pas besoin. Quelle que soit cette partie, incluez le code TypeScript ci-dessous.

 

 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 crée des objets TypeScript possède également de nombreuses fonctionnalités utiles, mais il n'est pas pratique d'en présenter davantage dans ce chapitre.

class Dog {
    hairColor: string;//class的所有属性必须在顶部全部声明,否则无法通过编译,这让类的创建更加规范;breed: string;//并且可以声明属性类型,如果给属性赋值的时候类型不正确也无法通过编译,当然,你也可以不声明类型或声明为any任何类型;    age: number;
    runSpeed: string;
    static instanceNumber: number = 0;//TS静态变量的声明就比较舒服了,在class的{}里面,保证了代码的干净    constructor(hairColor, breed, age) {this.hairColor = hairColor;this.breed = breed;this.age = age;
        Dog.instanceNumber++;
    }
    shout() {
        console.log('汪!汪!汪!我是一只' + this.age + '岁的' + this.hairColor + this.breed);
    }
    run() {this.runSpeed = '10m/s';
        console.log('吃我灰吧,哈哈!本狗的速度可是有' + this.runSpeed);
    }
    gnawBone() {
        console.log('这是本狗最幸福的时候');
    }
    getInstanceNumber() {return Dog.instanceNumber;
    }
}
let dog1 = new Dog('白色', '贵宾', 2);
let dog2 = new Dog('棕色', '泰迪', 1);
let dog3 = new Dog('黑色', '土狗', 3);
dog1.shout();//log: '汪!汪!汪!我是一只2岁的白色贵宾'dog2.shout();//log: '汪!汪!汪!我是一只1岁的棕色泰迪'dog3.shout();//log: '汪!汪!汪!我是一只3岁的黑色土狗'console.log(dog1.getInstanceNumber());//log: 3;

类的抽象

  上面的例子是我们明确知道要创建一个对象(实例)dog,但实际开发当中是没有人告诉我们需要创建哪些对象的,领导给我们的只有需求,所以我们要分析需求的业务逻辑,把需求分解成一个个对象。

  比如说现在领导给我们一个需求:做一个超市收银系统,分为两种角色:收银员和管理员,收银员可以查询物品信息、统计价格、录入账单信息、打印小票,管理员可以查看账单信息、统计账单信息。

  注意需求中的名词:收银员、管理员、物品信息、账单、小票,这些就是天然的对象,这是最初步的抽象。

  让我们再注意动词:查询、统计、录入、打印,我们是不是也可以抽象成对象?查询器?统计器?

  然后我们开始coding吧,不要纠结自己的抽象是否完美,作者很赞同Facebook的一句标语:Done is better than perfect(比完美更重要的是完成).

  当某个对象的代码不断膨胀,慢慢超出控制的时候(作者自己的的标准是一个对象尽量不超过300行代码),这时候你就得考虑更深层次的抽象了,查找这个对象里代码比较多的属性、方法、然后抽象成另一个对象,把新对象作为原先对象的成员(属性)。

 

function Dog(){
    this._tail = new Tail();//把尾巴tail抽象成另一个对象,作为dog的一个属性;
}

 

 

  当然,你成了老司机后可以一开始就把一个对象再抽象出许多成员对象,随你喜欢。

后话

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

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

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

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn