关于javascript中this的那些事

Mar 18, 2016

this是Javascript语言中的一个关键字!(不是变量,也不是属性)它是面向对象编程范例的核心之一。this没有作用域的限制,嵌套函数不会从调用它的函数中继承到this!

this运用的6种场景:

1.如果this所位于的函数被作为方法调用,此时this的值指向调用这个函数的对象

var demo = {
    speak: "my name is demo!",
    test: function() {
        console.log(this.speak);
    }
};
demo.test();//my name is demo!

2.如果this所位于的嵌套函数中被作为函数调用,在非严格模式下,此时this指向全局对象!(运行于浏览器时,指向Windows)

var demo = {
    test: function() {
        function inner_test() {
            console.log(this);
        }
        inner_test();
    }
};
demo.test();//windows

3.如果this所位于的嵌套函数中被作为函数调用,在严格模式下,此时this指向undefined

"use strict";
var demo = {
    test: function() {
        function inner_test() {
            console.log(this);
        }
        inner_test();
    }
};
demo.test();//undefined

4.如果this所位于的嵌套函数中被作为构造函数调用,此时this指向这个新生成的对象

var goble_num = 1;
function demo() {
    this.goble_num = 2;
}
demo();
console.log(goble_num);//2,此时this指向全局对象
goble_num = 1;//恢复全局变量goble_num
var d = new demo();
console.log(d.goble_num);//2
console.log(goble_num);//1

5.如果this所位于的嵌套函数调用了apply或call函数,此时this指向apply或call函数的第一个参数

var num = 1;
function demo(arg) {
    console.log(this.num, arg);
}
var o = {};
o.num = 2;
o.demo = demo;

// 用法1: 改变this指向
o.demo.apply();//1, apply()的参数为空时,默认调用全局对象
o.demo.apply(o, ['demo']);//2 ,apply传入 参数数组
o.demo.call(o, 'demo');//2 , call传入 参数列表

// 用法2: 借用别的对象到方法
var Person1  = function () {
    this.name = 'demo';
}
var Person2 = function () {
    this.getname = function () {
        console.log(this.name);
    }
    Person1.call(this); // 借用Person1的属性和方法,来实现继承
}
var person = new Person2();
person.getname();       // demo

6.如果this在HTML的标签中被当做事件绑定回调函数的参数传入 ,此时this指向触发事件的对象 [object HTMLElement]

7.ES5中的bind来为函数绑定this

var obj = {
    name: 'this demo'
}

function demo() {
    console.log(this.name);
}


var demo1 = demo.bind(obj); // 不立即执行demo,而返回一个以obj为this的新函数demo1
demo1(); // this demo

// 手写一个类bind函数的实现
function test (b) {
  console.log(this.a , b)
}

test.bind = function() {
  var testOld = this // 作为方法使用,此时this指向test函数
  var newThis = [].shift.call(arguments) // 借用数组的方法,获取第一个参数
  return function () {
    var args = [].slice.call(arguments) // 借用数组的方法,将arguments转换为数组
    testOld.apply(newThis, args)
  }
}

var test1 = test.bind({
  a: 'this a'
})

test1('no, this b') // this a no, this b

8.ES6中的 箭头函数 ,默认绑定了执行环境的this,实现this继承

const obj = {
    a: function() {
        console.log(this) // 常规写法
    },
    b: () => {
        console.log(this) // 按箭头函数定义的方法
    },
    c: function() {
        let test = () => {
            console.log(this)
        }
        test() // 可以理解为:执行方式同下面的方法d,默认绑定了this
    },
    d: function() {
        let test = function () {
            console.log(this)
        }
        test.call(this)
    }
}
obj.a()  // obj
obj.b()  // window
obj.c()  // obj
obj.d()  // obj

// 特性:不能用call方法修改里面的this
obj.b.call('abc') // window