【前端面试题】一文搞懂JavaScript this指向问题
JavaScript中的this代表的是当前行为执行的主体,在JavaScript中主要研究的都是函数中的this,但并不是说只有在函数里才有this,this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。
1. 函数调用
函数执行时首先看函数名前面是否有.,若有,.前面是谁,this就是谁。没有的话this就是window。
function fn() { console.log(this); } let obj = { fn: fn }; fn(); // this -> window obj.fn(); // this -> obj function sum() { fn(); } sum(); // this -> window let obj2 = { sum: function () { console.log(this); fn(); }, }; obj2.sum(); // sum中的this -> obj2 // sum中fn中的this -> window
2. 自执行函数
自执行函数中的this永远是window。
(function () { console.log(this); //this -> window })(); ~(function () { console.log(this); //this -> window })();
3. 事件绑定
-
DOM零级事件绑定
oDiv.onclick = function () { // this -> oDiv };
-
DOM二级事件绑定
oDiv.addEventListener( click, function () { // this -> oDiv }, false );
-
在IE6~8下使用attachEvent,默认的this就是指的window对象
oDiv.attachEvent(click, function () { // this -> window });
4. 构造函数
在构造函数模式中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的一个实例。
function Person(name, age) { this.name = name; this.age = age; this.do = function () { console.log(this); }; } var p1 = new Person(Jack, 18); p1.do(); // this -> p1实例对象
类中某一个属性值(方法),方法中的this需要看方法执行的时候,前面是否有.,才能知道this是谁。
function Fn() { this.x = 100; this.getX = function () { console.log(this.x); }; } let f1 = new Fn(); f1.getX(); // this -> 100 let ss = f1.getX; ss(); // this -> undefined
5. call()、apply()和bind()
详情请点击:
6. 箭头函数
(1)箭头函数不绑定this。
箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this。如果没有,则this是window。
let btn1 = document.getElementById(btn1); let obj = { name: kobe, age: 39, getName: function () { btn1.onclick = () => { console.log(this); // this -> obj }; }, }; obj.getName();
(2)若上一层并不存在函数,this指向又是谁?
let btn2 = document.getElementById(btn2); let obj = { name: kobe, age: 39, getName: () => { btn2.onclick = () => { console.log(this); // this -> window }; }, }; obj.getName();
上例中,虽然存在两个箭头函数,其实this取决于最外层的箭头函数,由于obj是个对象而非函数,所以this指向为window。
(3)用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略
let obj = { birth: 1990, getAge: function (year) { let fn = year => year - this.birth; // this.birth -> 1990 return fn.call({ birth: 2000 }, year); // 第一个参数被忽略,this.birth -> 1990 }, }; console.log(obj.getAge(2018)); // 28
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
《软件项目经验总结》