ES6中的类和对象继承
Posted dhui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6中的类和对象继承相关的知识,希望对你有一定的参考价值。
在 javascript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的:
属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)
1.2 类 class
类抽象了对象的公共部分,它泛指某一大类(class)
对象特指某一个,通过实例化一个具体的对象
面向对象的思维特点:
1、抽取(抽象)对象共用的属性和行为组织(封装)成一个类(模板)
2、对类进行实例化,获取类的对象
1.3 创建类
语法:
class name { // class body }
创建实例:
var xx = new name();
注意:类必须使用 new 实例化对象
1.4 类 constructor 构造函数
constructor() 方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过 new 命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动创建一个 constructor()
注意:
1、通过 class 关键字创建类,类名习惯性定义首字母大写
2、类里面有个 constructor 构造函数,可以接收传递过来的参数,同时返回实例对象
3、constructor 函数只要 new 生成实例时,就会自动调用这个函数,如果不写这个函数,类也会自动生成这个函数
4、生成实例 new 不能省略
5、语法规范:创建类 类名后面没有小括号,生成实例 类名后面加小括号,构造函数不需要加 function
1.5 类添加方法
语法:
class Person { constructor(name, age) { this.name = name; this.age = age } say() { console.log(‘hello, ‘ + this.name) } }
function Father(name, age) { this.name = name; this.age = age } Father.prototype.say = function() { console.log(‘I have lots of experience.‘) }
类的继承语法:
class Father{ // 父类 } class Son extends Father { // 子类继承父类 }
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的,如果子类里面没有,就去查找父类有没有这个方法,如果有就执行父类的这个方法(就近原则)
实例:
class Father { say() { return ‘this is father‘ } } class Son extends Father { // 这样子类就继承了父类的属性和方法 say() { return ‘this is son‘ // return super.say(); //super调用父类的方法,则输出‘this is father‘ } } let son = new Son(); son.say(); // ‘this is son‘
2.2 super 关键字
super 关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数。
class Father { constructor(x, y){ this.x = x; this.y = y; } sum(){ console.log(this.x + this.y) } } class Son extends Father { constructor(x, y) { super(x, y); // 调用了父类中的构造函数constructor this.z = z; //定义子类独有的属性 } } ? let son = new Son(1, 2); // 实例化了子类 son.sum();
注意: 子类在构造函数中使用super, 必须放到 this 前面 (必须先调用父类的构造方法,再使用子类构造方法),否则新建实例时会报错(this is not defined)
因为子类没有自己的this对象,而是继承父类的this对象。如果不调用super方法,子类就得不到this对象。
注意:
1、在 ES6 中没有变量提升,所以必须先定义类,才能通过类实例化对象
2、类里面的共有属性和方法一定要加 this 使用
3、类里面的 this 指向问题
4、constructor 里面的 this 指向实例对象,方法里面的 this 指向这个方法的调用者
let that; let _that; class Star { constructor(uname, age) { console.log(this); // this 指向创建的实例对象 Star{} that = this; this.uname = uname; this.age = age; } sing() { // 这个里面的 this 指向的是实例对象 ldh, 因为ldh调用了这个函数 _that = this; console.log(_that); //实例对象,ldh } } var ldh = new Star(‘刘德华‘); console.log(that === ldh); //true ldh.sing(); console.log(_that === ldh); //true
2.3 call()
fun.call(thisArg, arg1, arg2, ...)
-
thisArg:当前调用函数 this 的指向对象
-
arg1, arg2:传递的其他参数
-
返回值就是函数的返回值,因为它就是调用函数
-
因此当我们想改变 this 指向,同时想调用这个函数的时候,可以使用 call,比如继承
核心原理:通过 call() 把父类型的 this 指向子类型的 this,这样就可以实现子类型继承父类型的属性。
function Father(name, age) { this.name = name; this.age = age; } function Son(name, age) { // this 指向Son构造函数的实例对象 Father.call(this, name, age) } const son = new Son(‘刘德华‘, 18); console.log(son);
核心原理:
① 将子类所共享的方法提取出来,让子类的 prototype 原型对象 = new 父类()
② 本质:子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象
③ 将子类的 constructor 重新指向子类的构造函数
function Father(name, age) { this.name = name; this.age = age; } Father.prototype.money = function() { console.log(‘father money‘); } function Son(name, age) { // this 指向Son构造函数的实例对象 Father.call(this, name, age) } // Son.prototype = Father.prototype; 这样直接赋值,如果修改了子原型对象,父原型对象也会跟着一起变化 即 console.log(Father.prototype) 也会有 exam 方法 Son.prototype = new Father(); // 此时 son的原型对象指向Father, 即console.log(Son.prototype.constructor); 指向 Father, 所以需要利用 constructor 指回原来的构造函数 Son.prototype.constructor = Son; Son.prototype.exam = function() { console.log(‘son exam‘); } const son = new Son(‘刘德华‘, 18); console.log(son); console.log(Father.prototype); console.log(Son.prototype.constructor);
图解:
-
类的所有方法都定义在类的 prototype 属性上;
-
类创建的实例,里面也有 __proto__ 指向类的 prototype 原型对象;
-
所以 ES6 的类它的绝大部分功能,ES5都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已;
-
所以 ES6 的类其实就是语法糖;
-
语法糖:语法糖就是一种便捷写法。简单理解,有两种方法可以实现同样的功能,但是一种写法更加清晰、方便,那么这个方法就是语法糖。
以上是关于ES6中的类和对象继承的主要内容,如果未能解决你的问题,请参考以下文章