文章目录
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
本章也是借鉴和学习 也望大家多多指教!