javascript的this在工作编写业务的过程中十分常用,面试中也是一个屡见不鲜的面试题,今天我们就来详解一下this的指向问题,首先来了解一下什么叫做this
什么叫做this
自身执行上下文就做作this,准确来说,this是指当前函数运行环境的运行时自动生成的一个对象;
this并不是一成不变的,他会根据当前函数执行环境会做出相应不同的指向;
this的指向
this的运行环境有以下几种:
全局使用
在非严格模式和严格模式下,在全局环境下的this是都是指向顶级对象window,在全局环境下运行的函数也是指向的window
console.log('非严格下的this',this,this===window); function fn(){ console.log('全局函数下执行的window',this,this===window); } fn();
使用"use strict"关键字即可开启严格模式
"use strict" console.log('严格模式下的this',this,this===window);
不是说全局环境下的this都是指向window,为什么全局环境下运行的函数也是指向的window呢,不是应该指向当前的函数的,javascript是一个面向对象的编程语言,声明的函数或者变量没有指定属于那个对象,那么它就会属于顶级对象window
function fn(){ console.log('全局函数下执行的window',this,this===window); } fn(); //在全局环境下调用函数就相当于 window.fn(); //他们俩个运行的结果是一样的
普通对象
普通对象里面定义的函数指向的是自身,但是唯有一个函数例外,那就是箭头函数,箭头函数的this,JavaScript规定他没有this,它需要去捕获最近作用域的this,而普通函数的this,是谁调用它,它的this就指向谁
let obj = { name: '若水', age: '20岁', help() { console.log('普通函数this', this, this == obj, this == window); }, artty: () => { console.log('箭头函数this', this, this == obj, this == window); } } obj.artty() obj.help()
obj对象中并没有this,所以箭头函数会向最近作用域查找,obj对象调用者为window所以箭头函数打印为window
构造函数
当我们使用new 关键字对一个函数进行使用的时候,他就是构造函数,构造函数里面的this取决于构造函数的实例对象
function Structure(name, age) { this.name = name; this.age = age; this.point = function () { console.log('实例对象普通函数的this', this); } this.arrow = () => { console.log('实例对象箭头函数的this', this); } } let obj = new Structure('若水', '20岁'); console.log(obj.name); obj.point(); obj.arrow();
这里我们会发现构造函数创建实例的时候,里面箭头函数的this不指向window了,而是和普通函数一样指向了构造函数的实例,这是因为箭头函数内部的this是捕获最近作用域的this,而构造函数通过new关键字使this指向了创建的实例对象,箭头函数是在构造函数里面定义的,所以在创建实例的时候,构造函数执行了,这时候箭头函数所在运行环境就是创造实例对象的环境,构造函数的this指向是由实例对象所定义的。所以箭头函数的this就会指向实例对象
改变this的方法
外层定义this
var name='前端' let obj={ name:'若水', fn(){ let that=this; setTimeout(function(){ console.log(this.name); console.log(that.name); },0) } }
通过这样的操作可以使得内部可以使用外部的this,防止this指向错误
箭头函数的方法
我们可以利用箭头函数会寻找就近作用域的this,实现this指向的改变
var name='前端' let obj={ name:'若水', fn(){ setTimeout(()=>{ console.log(this.name); console.log(this.name); },0) } }
call方法
call获得this指向后会立即执行,传递参数往后传就行了
function fn() { console.log(this.name); } let obj={name:'三千弱水'}; fn.call(obj);
apply方法
apply方法获得this指向后会立即执行,不过他接受的参数是一个数组
//定义一个数组使用apply方式获取最大值 let arr = [1, 66, 3, 99, 4]; //这里的Math.max方法不接受一个数组的数据,我们就要使用到这个方法 let max = Math.max.apply(null, arr);
bind方法
bind方法获取this后不会立即执行而是会返回一个改变this后的函数
function fn() { console.log(this.name); } let obj={name:'三千弱水'}; //因为有返回值,所以需要接受一下,然后调用函数就可以调用返回值 let f=fn.bind(obj); f()
祝大家每天开开心心的,坚持努力,无惧未来!