JavaScript中的this

125 阅读2分钟

准备把重心放到前端,把前端之前留的一些问题,从头整理明白

this指向问题

this绑定方式
  • 默认绑定
  • 隐式绑定
  • 硬绑定
  • new绑定

默认绑定,在不能应用其它绑定规则时使用的默认规则,通常是独立函数调用。

//在非严格模式下,this指向全局变量,严格模式this指向undefined
function sayHi(){
    console.log('Hello,', this.name);
}
var name = 'demo';
sayHi();

隐式绑定,听名字感觉最为复杂

<!--通过obj.fun()隐式绑定-->

function sayHi(){
    console.log('Hello,', this.name);
}
var person = {
    name: 'demo',
    sayHi: sayHi
}
var name = 'Wiliam';
person.sayHi();

<!--虽然sayHi()在外部声明,在执行person.sayHi()方法时,会将this隐式绑定到上下文对象person上-->
<!--输出Hello,demo-->


<!--对象属性链中只有最后一层会影响到调用。-->

function sayHi(){
    console.log('Hello,', this.name);
}
var person2 = {
    name: 'Christina',
    sayHi: sayHi
}
var person1 = {
    name: 'demo',
    friend: person2
}
person1.friend.sayHi();
<!--输出Hello,Christina-->

<!--来一个陷阱-->
function sayHi(){
    console.log('Hello,', this.name);
}
var person = {
    name: 'demo',
    sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi();
<!--Hi()指向sayHi并没有person什么关系,sayHi中的this此时为默认绑定,指向全局name-->
<!--输出Hello,Wiliam-->

<!--再来一个陷阱,回调函数-->
function sayHi(){
    console.log('Hello,', this.name);
}
var person1 = {
    name: 'demo',
    sayHi: function(){
        setTimeout(function(){
            console.log('Hello,',this.name);
        })
    }
}
var person2 = {
    name: 'Christina',
    sayHi: sayHi
}
var name='Wiliam';
person1.sayHi();
setTimeout(person2.sayHi,100);
setTimeout(function(){
    person2.sayHi();
},200);
<!--输出Hello,Wiliam // 回调函数默认绑定-->
<!--输出Hello,Wiliam //person2.sayHi为变量赋值,this为默认绑定-->
<!--输出Hello,Christina //隐式绑定-->

硬绑定 call,apply,bind

<!--使用call,apply,bind方法直接改变this指向-->
function sayHi(){
    console.log('Hello,', this.name);
}
var person = {
    name: 'demo',
    sayHi: sayHi
}
var name = 'Wiliam';
var Hi = person.sayHi;
Hi.call(person); //Hi.apply(person)

<!--输出Hello,demo-->

<!--硬绑定出现绑定丢失情况-->
function sayHi(){
    console.log('Hello,', this.name);
}
var person = {
    name: 'demo',
    sayHi: sayHi
}
var name = 'Wiliam';
var Hi = function(fn) {
    fn();
}
Hi.call(person, person.sayHi); 

<!--输出Hello,Wiliam-->
<!--//当为参数使用时,应注意到底是person.sayHi还是person.sayHi(),此时对应的上下文是不一样的-->

new绑定

<!--this直接绑定到创建对象上-->

绑定优先级

new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

箭头函数中的this

<!--箭头函数中的this继承于外层代码中的this.-->