Class、原型、原型链、this指向

this指向

this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定,this最终指向调用它的对象。

1.函数调用模式

当一个函数并非一个对象的属性时,那么它就是被当做函数来调用的。在此种模式下,this被绑定为全局对象,在浏览器环境下就是window对象

function that() {
    let q = 'this is a cainiao web '
    console.log(this.q); /* undefined */
    console.log(this); /* window */
}
that();
2.方法调用模式

当函数被保存为一个对象的属性时,它就可称为这个对象的方法。当一个方法被调用时,this被绑定到这个对象上。如果调用表达式包含一个提取属性的动作(. 或 []),那么它被称为方法调用

let obj = {
    name:'对象',
    married:function()  {
        console.log(this.name);
    }
}
obj.married()

这里的this指向的对象是o,因为调用这个married()函数是通过o.sayName()执行的。

let obj = {
    name:'对象',
    married:{
        b:function()  {
            console.log(this.name);
        }
    }
}
obj.married.b()

因为是o.married调用的这个函数,所以指向married这个对象

3.构造函数调用模式

如果在一个函数前面加上new关键字来调用,那么就会创建一个连接到该函数的prototype成员的新对象,同时,this会被绑定到这个新对象上。这种情况下,这个函数就可以成为此对象的构造函数。

function Person() {
    console.log('这是一个构造函数');
    console.log(this); /* Person{} */
}
let person = new Person()

当用new关键字,返回的是一个对象,this指向的就是那个返回的对象;
如果返回的不是对象,this还是指向函数的实例,虽然null属于对象,但是返回null依然指向函数实例

4.apply和call调用模式

JS中,函数也是对象,所有函数对象都有两个方法:apply和call,这两个方法可以让我们构建一个参数数组传递给调用函数,也允许我们改变this的值
在全局范围内,this指向全局对象(浏览器下指window对象)

对象函数调用时,this指向当前对象

全局函数调用时,应该是指向调用全局函数的对象。

使用new关键字实例化对象时,this指向新创建的对象

当用apply和call上下文调用的时候指向传入的第一个参数

关于class类

class是es6的新特性之一,通过class关键字来定义一个类,可以理解class为一个模板,它的本质就是一个函数,可以通过constructor构造方法来构造一些属性,定义方法时,不需要加function,方法之间也不需要逗号隔开,然后可以通过new关键字来实例化这个类
例如:现在定义一个学生的类,定义了两个属性和一个方法,其中this指向将要实例化的对象:(class类名首字母需要大写)

class Student {
    constructor(name,age){
        this.name=name
        this.age=age
    }
    say(){
        console.log(`你好,我叫${this.name},今年${this.age}岁了`)
    }
}

现在可以通过new关键字实例化一个对象:

const xiaoMing = new Student('小明', 20)
console.log(xiaoMing.name)
console.log(xiaoMing.age)
xiaoMing.say()

在这里插入图片描述

class的继承

作用:子类可以继承父类构造函数的属性和方法
怎么做:子类可以通过extends和super关键字来继承父类

例如:现在可以定义一个People的父类

class People {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    say() {
        `我叫${this.name},我的年龄是${this.age}`
    }
}

然后定义一个子类Student,让他继承父类的属性和方法,需要使用extends并在constructor中使用super将子类属性传给父类

class Student extends People {
            constructor(name, age, number) {
                super(name, age)
                this.number = number
            }
            sayHi() {
                console.log(`我叫${this.name},我的学号是${this. number}`)
            }
        }

const xiaoMing = new Student(‘小明’, 20, 222666)
console.log(xiaoMing.name)
console.log(xiaoMing.number)
xiaoMing.say()
xiaoMing.sayHi()
在这里插入图片描述
可以看到通过Student实例化出的小明,继承了People 类的name和age属性以及say方法

原型

概念:

js为每个函数提供的一个公共空间

隐式原型和显式原型

隐式原型:每个实例都有隐式原型,就是__proto__
显式原型:每个class都有显式原型,就是prototype
关系:实例的隐式原型指向对应class的显式原型

console.log(xiaoMing.__proto__)
console.log(Student.prototype)
console.log(Student.prototype===xiaoMing.__proto__)

在这里插入图片描述
构造函数Student中显式原型为prototype,指向sayHi函数,实例Xiaoming隐式原型__proto__也指向了Student中prototype的sayHi函数,两者是全等的

基于原型的执行规则:

获取属性或方法时先在自身的属性和方法中查找,找不到就去隐式原型__proto__中查找

console.log(Student.prototype.__proto__)
console.log(People.prototype)
console.log(Student.prototype.__proto__===People.prototype)

People是Student的父类,所以Student的显式原型的隐式原型指向了People的显示原型
当Xiaoming需要带调用say方法是,先在自身找,找不到去Student找,找不到在去People找,一直找到Object的原型上去(Object上的隐式原型指向null),这样就形成了原型链

类型判断instanceof

作用:通过instanceof可以判断一个实例是否属于某种类型,在继承关系中可以判断一个实例是否是该class构建出来的,或者是这class的父类

//true,xiaoMing 是通过Student构建出来的
console.log(xiaoMing instanceof People) 
//true,People是xiaoMing的父类
console.log(xiaoMing instanceof Object) 
//true,Object是所有class的父类
console.log(xiaoMing instanceof Array)
//false

本质:instanceof就是顺着原型链向上查找__proto__,如果能够对应到class的prototype就返回true,找不到就返回false
本章也是借鉴和学习 也望大家多多指教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值