1.1 对象
在 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)
}
}
2.1 继承
现实中的继承:子承父业,比如我们都继承了父亲的姓。
程序中的继承:子类可以继承父类的一些属性和方法。
ES6 之前没有提供 extends 继承,我们可以通过 构造函数 + 原型对象 模拟实现继承,被称为组合继承。示例:
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()
call() 方法调用一个对象。简单理解即调用这个函数, 并且修改函数运行时的 this 指向。
fun.call(thisArg, arg1, arg2, ...)
- thisArg:当前调用函数 this 的指向对象
- arg1, arg2:传递的其他参数
- 返回值就是函数的返回值,因为它就是调用函数
- 因此当我们想改变 this 指向,同时想调用这个函数的时候,可以使用 call,比如继承
2.4 借用构造函数继承父类型属性
核心原理:通过 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);
2.5 借用原型对象继承父类型方法
一般情况下,对象的方法都在构造函数的原型对象中设置,那么通过构造函数创建的对象就会继承原型的属性和方法。
核心原理:
① 将子类所共享的方法提取出来,让子类的 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);
图解:
2.6 类的本质
1、class 本质还是 function;
2、类的所有方法都定义在类的 prototype 属性上;
3、类创建的实例,里面也有 __proto__ 指向类的 prototype 原型对象;
4、所以 ES6 的类它的绝大部分功能,ES5都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已;
5、所以 ES6 的类其实就是语法糖;
6、语法糖:语法糖就是一种便捷写法。简单理解,有两种方法可以实现同样的功能,但是一种写法更加清晰、方便,那么这个方法就是语法糖。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。