javascript中this指向问题(面试必考)

javascript中this指向问题

1.为什么会有this

1.看下面一段代码

//不使用this
function myName(context){
    return context.name.toLocaleUpperCase();
}

function introduction(context){
    console.log(`My name is ${myName(context)}`)
}
let ming = {
    name: "ming",
}
let yong = {
    name: "yong"
}
introduction(ming); //my name is MING
introduction(yong); //my name is YONG


//使用this
function myName(){
    return this.name.toLocaleUpperCase();
}

function introduction(){
    console.log(`My name is ${myName.call(this)}`)
}
let ming = {
    name: "ming",
}
let yong = {
    name: "yong"
}
introduction.call(ming); //my name is MING
introduction.call(yong); //my name is YONG

如果你不适用this,就要使用函数参数来保存你的一个默认的环境值,当函数参数较多的时候容易乱,总上所述使用this是比较方便的。

2.this究竟是什么

首先: 函数(非箭头函数)里面的this是由他的执行位置决定的,即函数在执行过程中会产生一个记录(执行上下文),其中this就是执行上下文的一个属性。

3.this指向问题

this的指向由几种方式

  1. 默认绑定
  2. 隐私绑定
  3. 显示绑定
  4. new 绑定
3.1默认绑定

1.独立函数调用使用默认绑定

function a(){
    "use strict"
    console.log(this.count)
}

function a1(){
    console.log(this.count);
}
var count = 1;

a1();//1
a();//Error

(function(){
    "use strict"
    a1(); //1
})()

代码解析:
从上面的代码中可以看出:
默认情况下函数独立执行,并在没有严格模式下this为window,
严格模式为undefined。

3.2隐式绑定

代码:

function a(){
    console.log(this.name)
}

var obj ={
    name: "ming",
    age: "1",
    foo: a
}
var obj2 = {
	obj1: obj
}
obj.foo(); //ming
obj2.obj1.foo(); //ming

隐式绑定: this为你的最后一层引用的执行上下文对象,例如上面的代码obj.foo() 中的this为obj,
上面的第二个obj2.obj1.foo()中的this为函数的最后一层引用为: obj1

注意:隐式丢失

function foo(){
	console.log(this);
}
var obj ={
name: "ming",
foo: foo
}
var foo = obj.foo;
foo(); //window

//将函数作为回调函数会发生隐式丢失问题,导致this为默认绑定 this为window
function d(fn){
	fn();
}
d(obj.foo); //this 为window;

此处隐式丢失了,this为默认绑定,为 window。
隐式丢失: 赋值或者是使用回调函数,导致隐式this会为window,这里的this是一个隐式丢失问题导致this为window。例如:setTimeout,setInterval中的this就是一种隐式丢失问题导致了this为默认绑定。

3.3显示绑定

1.使用apply和bind进行绑定this指向,具体的使用看另外一篇文章

function a(){
    console.log(this);
}
obj = {
    name: "ming"
}
a.call(obj);  //this 为obj
a.apply(obj); //this为 obj

使用call,apply 进行修改this

注意: 显示绑定不能直接解决隐式丢失的问题,不过显示的一种模式可以,即硬绑定。
硬绑定:

function a(){
    console.log(this);
}
obj = {
    name: "ming",
}
function bind(fn,obj){
    return function (args){
        fn.call(obj,args);
    }
}
var foo = bind(a,obj);
foo(); //this 为obj

由于硬绑定是一种常见的模式,所以出现了bind,即function.prototype.bind。

3.4new绑定

new 绑定
new 创建对象的步骤

1.创建(或者说构造)一个全新的对象
2.这个新对象会被执行链接
3.这个新对象会绑定到函数调用的this
4.如果函数没有返回其他对象,那么new表达式中函数调用会自动返回这个新对象。

优先级问题

1.默认绑定<隐私绑定<显示绑定<new 绑定

function ming(){
    console.log(this)
}

var obj1 = {
    name: "ming",
    foo: ming,
}
var obj2 = {
    name: "ming1"
}
//默认绑定
ming(); // window
//隐式绑定
obj1.foo(); // obj1;
//显示绑定
obj1.foo.call(obj2); //obj2
//new 绑定
let bindfoo = ming.bind(obj2);
var obj3 = new bindfoo(); //obj3
5被忽略的this

使用call,apply或者bind第一个参数传入null或者是undefined,则会进行默认的this绑定,this为window或者严格模式为undefined

function test(){
    console.log(this)
}

let obj = {
    name: "ming",
    foo: test
}
obj.foo.apply(); //window
obj.foo.call(null); //window;
obj.foo.bind(null)(); //window;

上述代码可以证明bind,apply,call绑定null或者undefined时,不会发生隐式绑定,this为window。

箭头函数的this

箭头函数的this和他的声明有关,箭头函数的this是声明的处父级的this。

function test(){
    return ()=>{
        console.log(this);// this 和test this相同
    }
}
test()(); // this 为 window
var obj = {
    name: "ming",
    foo: test,
}
obj.foo()(); // this 为 obj
obj.foo.bind({a:"1"})()() //{a:"1"}

上面的代码可以看出 箭头函数的this和test的this一致,改变的test的this,箭头函数的this也会改变,即箭头函数的this和他的声明有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值