今天小编给大家分享一下JavaScript中this指向的问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
例子1
var fn = function () { console.log(this === window); }; fn(); // true
例子2
let fn = function () { console.log(this === window); }; fn(); // true
例1使用var定义在全局作用域中,例2使用let定义在块作用域中,但内部的this都指向window
原因:函数直接调用,会做默认绑定,可类比为 fn.call(undefined),call 第一个参数是null或undefined,那么 this 将指向全局对象
常见面试题
示例1:
var a = 3; function c() { alert(a); //3 } (function () { var a = 4; c(); })();
示例2:
var name = "123"; var obj = { name: "456", print: function () { function a() { console.log(this.name); //123 } a(); }, }; obj.print();
无论面试题设计的多花里胡哨,只要记住 普通函数直接调用,默认绑定,this指向全局 便可知道函数内部this指向window
如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上
let obj = { name: "123", fn: function () { console.log(this.name); //123 }, }; obj.fn();
如果函数调用前存在多个对象,this指向距离调用自己最近的对象
let obj = { name: "123", o: { name: "456", func: function () { console.log(this.name); }, }, }; obj.o.func(); //456
隐式丢失:通过变量赋值将对象中的函数变成普通函数
var name = "1"; let obj = { name: "2", fn: function () { console.log(this.name); }, }; let fn1 = obj.fn; fn1(); //1
fn1 直接调用,默认绑定,this指向全局
显示绑定:通过call、apply以及bind方法改变this的行为
let obj1 = { name: "1", }; let obj2 = { name: "2", }; let obj3 = { name: "4", }; var name = "3"; function fn() { console.log(this.name); } fn(); //3 默认绑定,this指向全局 fn.call(obj1); //1 this指向obj1 fn.apply(obj2); //2 this指向obj2 fn.bind(obj3)(); //4 this指向obj3
拓展:call、apply、bind 相同点与不同点
相同点:改变this的指向
不同点:
call 第二个参数传入一个参数列表
apply 第二个参数传入一个参数数组
bind 第二个参数传入一个参数列表,返回一个函数,不会立即执行
this指向生成的新对象
function Person(name, age) { this.name = name; this.age = age; } const p1 = new Person("1", 20); console.log(p1); // {name:'1', age:20}
默认绑定外层 this
例1
var name = "1"; let obj = { name: "2", fn: function () { setTimeout(function () { console.log(this.name); //1 }); }, }; obj.fn();
setTimeout实际是window.setTimeout,因此函数内部this指向window,打印结果为1
例2
var name = "1"; let obj = { name: "2", fn: function () { setTimeout(() => { console.log(this.name); //2 }); }, }; obj.fn();
由于使用了箭头函数,默认绑定外层this,this指向函数fn
fn由obj调用,this隐式绑定到obj,最后打印的结果为2
例3:
var name = "window"; var student = { name: "1", fn: function () { var fn2 = () => { console.log(this.name); }; fn2(); }, fn3: () => { console.log(this.name); }, }; student.fn(); // '1' student.fn3(); // 'window'
student.fn() 内部执行的是函数fn2,由于fn2是直接调用,默认绑定到window上,但由于fn2是箭头函数,绑定外一层this,所以this指向函数fn,fn由student对象调用,因此最终this指向student
student.fn3() 隐式绑定this指向student,由于fn3是箭头函数,默认绑定外一层的this,最终this指向window
例4:防抖函数
function debounce(fn, delay) { let timer = null; return function () { clearTimeout(timer); timer = setTimeout(() => { //谁调用,this指向谁 fn.apply(this, arguments); }, delay || 1000); }; } function fn() { console.log(this); //document } document.addEventListener("click", debounce(fn));
setTimeout函数中的this默认指向window,因为是箭头函数,默认绑定外层this,因此this指向匿名函数,匿名函数由document调用,所以this指向document。再通过apply将函数fn的this绑定到document上,因此打印出document
显式绑定(bind>call/apply) > 隐式绑定 > 默认绑定
1. 隐式绑定 > 默认绑定
function bar() { console.log(this); //info } const info = { bar: bar, }; info.bar();
2. 显示绑定 > 隐式绑定
var fullName = "global"; const info = { fullName: "1", getName: function () { console.log(this.fullName); }, }; info.getName.call(null); //global
3. bind > apply/call
function bar() { console.log(this); //{age: 1} } bar.bind({ age: 1 }).call({ age: 2 });
函数中的this绑定在 { age: 1 } 上,即使后面又使用了call绑定
以上就是“JavaScript中this指向的问题怎么解决”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。