翼度科技»论坛 编程开发 JavaScript 查看内容

JS深入学习笔记 - 第二章.类和对象

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
3.类和对象

3.1面向对象

这里顺带提一句学习JAVA时,老师说的面向对象和面向过程的区别:
面向过程:强调做什么事情,具体什么步骤。举个把大象放进冰箱的例子:

  • 打开冰箱门
  • 把大象放进冰箱
  • 关上冰箱门
面向对象:强调的是做动作的主体(称之为对象)

  • 冰箱:打开操作
  • 冰箱:放的操作(放的可以是大象也可以是老鼠)
  • 冰箱:关闭的操作

 
面向对象的思维特点:

  • 抽取(抽象)对象共用的属性和行为封装成一个类(模板)
  • 对类进行实例化,创建类的对象(具体的东西)
3.2对象

现实中:对象是一个具体的事物,比如一本书、一辆车、一个人。
在js中:对象是一组无序的相关属性和方法的集合,所有的事物都是对象,如:字符串、数组、数值、函数等。
 
对象是由属性方法组成的:

  • 属性:事物的特征,在对象中用属性来表示
  • 方法:事物的行为,在对象中用方法来表示
3.3 类

ES6中新增了类的概念,可以使用class关键字来声明一个类,之后以这个类来实例化对象
类抽象了对象的公共部分,它泛指某一大类,
对象特指**某一个,通过类实例化一个具体的对**象。
类的本质:

  • class本质还是function
  • 类所有的方法都定义在类的prototype属性
  • 类创建的实例里面也有__ proto__ 指向类的prototype原型对象
  • 所以ES6的类的绝大部分功能。ES5都可以做到,新的class的写法只是让对象原型的写法更加清晰、更面向对象编程的语法。
  • 所以ES6的类其实就是语法糖
  1.     class Father {
  2.         
  3.     }
  4.     console.log(Father instanceof Function); //true
  5.     //(1)类有原型对象prototype
  6.     console.log(Father.prototype);
  7.     //(2)类的原型对象prototype 里面有 constructor 指向类本身
  8.     console.log(Father.prototype.constructor);
  9.     //(3)类可以通过原型对象添加方法
  10.     Father.prototype.speak = function () {
  11.       console.log("speak");
  12.     };
  13.     //(4)类创建的实例对象有 __proto__ 指向类的原型对象
  14.     const zooey = new Father();
  15.     console.dir(zooey.__proto__ === Father.prototype); //true
复制代码
 3.4创建类和实例化对象
 
  1. //创建类
  2. class Star {
  3.      //共有属性放在constructor中
  4.       constructor(uname, age) {
  5.         this.name = uname;
  6.         this.age = age;
  7.       }
  8.     }
  9.     // 利用类实例化对象
  10.     const ldh = new Star("刘德华", 19);
  11.     const syz = new Star("孙燕姿", 18);
  12.     //打印查看
  13.     console.log(ldh);
  14.     console.log(syz);
复制代码

  • 注意:

  • 通过class关键字创建类,类名首字母大写。
  • 类里面有一个constructor函数,可以接收传递过来的函数,同时返回实例对象。
  • 只要使用new生成实例时,就会调用constructor函数,如果我们不写这个函数, 类也会自动生成这个函数
 
3.5类中添加方法
  1. //创建类
  2.     class Star {
  3.       //共有属性放在constructor中
  4.       constructor(uname, age) {
  5.         this.uname = uname;
  6.         this.age = age;
  7.       }
  8.       sing(song) {
  9.           //方法中可以this.使用实例属性
  10.         console.log(this.uname + "会唱" + song);
  11.       }
  12.     }
  13.     // 利用类实例化对象
  14.     const ldh = new Star("刘德华", 19);
  15.     const syz = new Star("孙燕姿", 18);
  16.     //打印查看
  17.     console.log(ldh);
  18.     console.log(syz);
  19.     ldh.sing("忘情水");
  20.     syz.sing("遇见");
复制代码
  

 
注意:

  • 类里面的所有函数(方法)不需要写function
  • 多个函数方法(包括构造函数)之间不需要用 ',' 分割
4 类的继承

现实中的继承:子承父业,比如我们都继承了父亲的
程序中的继承:子类可以继承父类的一些属性方法
4.1使用extends关键字实现继承

 
  1.    //创建父类类
  2.     class Father {
  3.       constructor(name, sex) {
  4.         this.name = name;
  5.         this.sex = sex;
  6.       }
  7.       money() {
  8.         console.log(1000);
  9.       }
  10.     }
  11.     // 创建子类并继承父类
  12.     class children extends Father {
  13.     }
  14.     const oldestSon = new children("伯邑考", "男");
  15.     const middleSon = new children("姬发", "男");
  16.     son.money();
复制代码
4.2super关键字

一个错误使用案例:
 
  1.     class Father {
  2.       constructor(x, y) {
  3.         this.x = x;
  4.         this.y = y;
  5.       }
  6.       total() {
  7.         return this.x + this.y;
  8.       }
  9.     }
  10.     class Son extends Father {
  11.       constructor(x, y) {
  12.         this.x = x;
  13.         this.y = y;
  14.       }
  15.     }
  16.     const son = new Son(1, 1);
  17.     console.log("结果:" + son.total());
复制代码

 
此时希望调用父类中的构造函数则需要使用到super
  1.     class Father {
  2.       constructor(x, y) {
  3.         this.x = x;
  4.         this.y = y;
  5.       }
  6.       total() {
  7.         return this.x + this.y;
  8.       }
  9.     }
  10.     class Son extends Father {
  11.       constructor(x, y) {
  12.         super(x, y);
  13.       }
  14.     }
  15.     const son = new Son(1, 1);
  16.     console.log("结果:" + son.total()); //结果:2
复制代码
 
思考:看到这里不知道你会不会和我有一样的困惑,此时没有super也可以实现 total方法的调用,所以 super存在真正的意义是什么呢
思考案例1:
 
  1.     class Father {
  2.       constructor(x, y) {
  3.         this.x = x;
  4.         this.y = y;
  5.       }
  6.       total() {
  7.         return this.x + this.y;
  8.       }
  9.     }
  10.     class Son extends Father {
  11.     }
  12.     const son = new Son(1, 1);
  13.     console.log("结果:" + son.total());
复制代码

 
那么就让我们停下来思考一下:
当我们给Son构造函数传递多个参数的时候,这时,输出的结果就不是我们想要的结果了,此时就必须使用super才能传递正确的参数了。
思考案例2:
 
  1.    class Father {
  2.       constructor(x, y) {
  3.         this.x = x;
  4.         this.y = y;
  5.       }
  6.       total() {
  7.         return this.x + this.y;
  8.       }
  9.     }
  10.     class Son extends Father {
  11.   
  12.     }
  13.     const son = new Son(1, "女", "zooey", 1);
  14.    
  15.     console.log("结果:" + son.total());//结果:1女
复制代码
真正意义上:
利用Son类创建实例son时,我们将实例son的参数传递给Son类的构造函数,
构造函数通过super()调用Father构造函数从而给this.x,this.y赋值,
从而使Father类中的total的方法能够找到 this.x,this.y,
从而实现了思考案例1的结果。

 
没有super时:

 
super关键字用于访问和调用对象父类上的函数,可以调用父类的构造函数,也可以调用父类的普通函数。
super调用父类的方法
 
  1.   class Father {
  2.       constructor(x, y) {
  3.         this.x = x;
  4.         this.y = y;
  5.       }
  6.       total() {
  7.         return this.x + this.y;
  8.       }
  9.     }
  10.    
  11.     class Son extends Father {
  12.       constructor(x, y, z) {
  13.         super(x, y);
  14.         this.z = z;
  15.       }
  16.       total() {
  17.         //子类方法中调用父类方法
  18.         return this.z + super.total();
  19.       }
  20.     }
  21.     const son = new Son(1, 1, 1);
  22.     console.log("结果:" + son.total());//3
复制代码
 
注意:子类的this赋值操作要放在super之后

 
注意事项:

  • 在 ES6 中类没有变量提升,必须先定义类,再实例化对象
  • 类里面共有是属性和方法一定要加this使用
 
  1.   class Star {
  2.         constructor(name, age) {
  3.           this.name = name;
  4.           this.age = age;
  5.           this.btn = document.querySelector("button");
  6.           this.btn.onclick = this.sing;
  7.         }
  8.         sing() {
  9.           console.log(this.name);
  10.         }
  11.       }
  12.       const ldh = new Star("刘德华", 18);
复制代码
 
4.3类中this指向

函数中的this一般指向调用者
下面的代码debug执行下,可以看到,sing()方法执行时,this是指向button的。

 
那么正确的做法是什么呢?
 
  1.       let _this;
  2.       class Star {
  3.         constructor(name, age) {
  4.           _this = this;
  5.           this.name = name;
  6.           this.age = age;
  7.           this.btn = document.querySelector("button");
  8.           //注意:因为这里是点击之后再调用,不是立即执行,所以是sing不是sing()
  9.           this.btn.onclick = this.sing;
  10.         }
  11.         sing() {
  12.             //使用 _this
  13.           console.log(_this.name);
  14.         }
  15.       }
  16.       const ldh = new Star("刘德华", 18);
复制代码
 
总结:全局声明一个this,然后调用后将它赋值给调用对象。
举一反三:react中,常用的另一个方法是使用bind绑定this
 
  1.   class Star {
  2.         constructor(name, age) {
  3.           this.name = name;
  4.           this.age = age;
  5.           this.btn = document.querySelector("button");
  6.           this.btn.onclick = this.sing.bind(this);
  7.         }
  8.         sing() {
  9.           console.log(this.name);
  10.         }
  11.       }
  12.       const ldh = new Star("刘德华", 18);
复制代码
来源:https://www.cnblogs.com/zry123/p/17701706.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具