2022前端面经---改变this指向问题(call、apply、bind)

简介: 2022前端面经---改变this指向问题(call、apply、bind)

面试题


请你讲一讲this指向如何改变?有哪几种方式?


问题剖析:


这种题其实就是考察你对js中的this指向有没有一个深刻的理解和认识,改变this指向问题是面试必问的,切入点就是改变this指向的三种方法!


问题解答:


复习(什么是this指向)


首先我们需要去回顾一个问题:什么是this指向呢?


我们必须要知道this是一个关键字,然后this的出现会有普通函数和箭头函数之分:


普通函数: 谁调用,this就指向谁,如果没有调用者,this默认指向window

箭头函数(es6):箭头函数的this是父级作用域的(精解:箭头函数外如果还有一个函数包裹,那么这个this指向的就是外包裹函数。如果箭头函数外没有外包裹函数,那么this就指向window)


场景一:



console.log(this);  //window


我们直接在控制台打印this,会发现打印出来的是window对象,默认情况下,this指向window对象。


场景二:




setTimeout(function(){
         console.log(111,this);  // 111 window
     },2000)


我们使用定时器,规定2秒后再去执行回调函数打印,最终打印结果为111 window,在这里要注意一下,根据浏览器的调用机制,定时器和计时器中回调函数打印this都会是window。


场景三:



<div id="box">click</div>
<script>
box.onclick = function() {
            console.log(this); //<div id="box">click</div>
        }
</script>


在事件中绑定this,我们点击click后可以发现,打印出来了dom元素,说明我们点击的是这个dom元素


场景四:



let obj = {
            name : 'lebron james',
            play : function(){
                console.log(this.name); 
            }
        }
        obj.play()  //lebron james


对象中this指向了调用者,该场景中调用者是obj,那么这个this指向的就是this的name,故打印出来了lebron james


场景五:



let obj1 = {
            name : 'davis',
            plays : ()=>{
                console.log(this);
            }
        }
        obj1.plays() // window


在字面量中直接定义的箭头函数无法继承该对象的this,而是往外再找一层,就找到了window,因为字面量对象无法形成自己的一层作用域.


改变this指向的三个方法


1. call()方法



let obj1 = {
        name : 'james',
        getName1 : function(a,b,c) {
            console.log(`getName ${this.name}`); // getName davis
            console.log(`参数:${a},${b},${c}`); // 参数:1,2,3
        }
    }
 let obj2 = {
        name : 'davis',
        getName2 : function() {
            console.log(`getName ${this.name}`);
        }
    }
 obj1.getName1.call(obj2)
 obj1.getName1.call(obj2,1,2,3)


  1. call 执行函数,并改变this指向为函数的第一个参数(在这里this指向改变为了传入的第一个参数obj2,this已经指向了obj2)
  2. call 可以传入多个参数


2. apply()方法



let obj1 = {
    name : 'james',
    getName1 : function(a,b,c) {
        console.log(`getName ${this.name}`); // getName davis
        console.log(`参数:${a},${b},${c}`); // 参数:1,2,3
    }
}
let obj2 = {
    name : 'davis',
    getName2 : function() {
        console.log(`getName ${this.name}`);
    }
}
obj1.getName1.apply(obj2,[1,2,3])


  1. apply 执行函数,并改变this指向为函数的第一个参数(同call)
  2. apply 只能传入两个参数,第二个参数只能是数组的形式


3. bind()方法




let obj1 = {
    name : 'james',
    getName1 : function(a,b,c) {
        console.log(`getName ${this.name}`); // getName davis
        console.log(`参数:${a},${b},${c}`); // 参数:1,2,3
    }
}
let obj2 = {
    name : 'davis',
    getName2 : function() {
        console.log(`getName ${this.name}`);
    }
}
let fn = obj1.getName1.bind(obj2,1,2,3)
fn()


  1. bind 改变this指向为第一个参数,但是不会自动执行函数,返回一个新的函数,需要手动执行才行
  2. bind 可以传入多个参数


个人经验总结


我们通过改变this指向的三种方式可以发现,call和apply是相似的,但是apply只能传入两个参数,第二个参数必须是数组形式。


bind是特殊的,它的特殊在于会返回一个新的函数,不会自动执行,需要我们自己手动执行


在我们项目开发中其实很少用到改变this指向,但是在面向对象过程中改变this指向倒是不经意间要使用的!


相关文章
|
2月前
|
前端开发 JavaScript 开发者
揭秘JavaScript魔法三剑客:call、apply、bind,解锁函数新世界,你的前端之路因它们而精彩!
【8月更文挑战第23天】在 JavaScript 的世界里,`call`、`apply` 和 `bind` 这三个方法常常让新手感到困惑。它们都能改变函数执行时的上下文(即 `this` 的指向),但各有特点:`call` 接受一系列参数并直接调用函数;`apply` 则接收一个参数数组,在处理不确定数量的参数时特别有用;而 `bind` 不会立即执行函数,而是创建一个新版本的函数,其 `this` 上下文已被永久绑定。理解这三个方法能帮助开发者更好地运用函数式编程技巧,提升代码灵活性和可维护性。
34 0
|
5月前
|
前端开发 JavaScript
【Web 前端】 js中call、apply、bind有什么区别?
【4月更文挑战第22天】【Web 前端】 js中call、apply、bind有什么区别?
【Web 前端】 js中call、apply、bind有什么区别?
|
5月前
|
前端开发 JavaScript
【前端面试】this的指向_不爱吃糖的程序媛夏天,web前端面试项目中的问题包括
【前端面试】this的指向_不爱吃糖的程序媛夏天,web前端面试项目中的问题包括
|
5月前
|
前端开发 JavaScript
前端 JS 经典:apply、call、bind
前端 JS 经典:apply、call、bind
92 0
|
5月前
|
前端开发 JavaScript
【Web 前端】说一下this指向?
【4月更文挑战第22天】【Web 前端】说一下this指向?
|
5月前
|
前端开发 JavaScript 网络架构
前端this指向详解
前端this指向详解
58 0
|
5天前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
|
5天前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
17 0
|
5天前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
5天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。