前端百题斩【014】——js中的这些“this”指向都值得了解

简介: 前端百题斩【014】——js中的这些“this”指向都值得了解

640.jpg

14.1 简介


this是javascript中的一个关键字,其使用方法类似于一个变量,是执行上下文中一个重要组成部分。其作用是可以在函数体内部获取当前的运行环境。


14.2 指向


每个函数的this是在调用的时候基于函数的执行环境绑定的,this的指向完全取决于函数的调用位置。(下面均是在浏览器环境下进行测试的结果)


  1. 在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;


console.log(this); // window
  1. 普通函数内部的this分两种情况,严格模式和非严格模式。


(1)非严格模式下,this 默认指向全局对象window


(2)严格模式下, this为undefined


function fun() {
    console.log(this); // window
}
  1. 对象内部方法的this指向调用这些方法的对象


(1)函数的定义位置不影响其this指向,this指向只和调用函数的对象有关;
(2)多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。


const obj = {
    a: 10,
    b: 20,
    add: function () {
        return this.a + this.b;
    }
};
console.log(obj.add()); // 30
const add = obj.add;
console.log(add()); // NaN
  1. 原型链中的方法的this仍然指向调用它的对象


const obj = {
    a: 10,
    b: 20
};
const prototypeObj = {
    add: function () {
        return this.a + this.b;
    }
};
Object.setPrototypeOf(obj, prototypeObj);
console.log(obj.add()); // 30
  1. 构造函数中的this与被创建的新对象绑定。


function Fun() {
    this.a = 10;
}
const fun = new Fun();
console.log(fun.a); // 10
  1. 当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它。(见后续代码)


  1. 通过bind方法绑定后, 函数将被永远绑定在其第一个参数对象上, 而无论其在什么情况下被调用。(见后续代码)


  1. 当函数被当做监听事件处理函数时, 其 this 指向触发该事件的元素(针对于addEventListener事件)


<button id="testId">按钮</button>
const btn = document.getElementById('testId');
btn.addEventListener('click', function() {
 console.log(this); // <button id="testId">按钮</button>
});
  1. 内联事件中的this指向分两种情况:
    (1)当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素


<button onclick="console.log(this)">按钮</button> // 输出该DOM节点
  1. (2)当代码被包括在函数内部执行时,其this指向等同于 函数直接调用的情况,即在非严格模式指向全局对象window, 在严格模式指向undefined


<button onclick="clickFun()">按钮</button>
function clickFun() {
 console.log(this); // window
}
  1. 对于延时函数内部的回调函数的this指向全局对象window(当然可以通过bind方法改变其内部函数的this指向)


function Fun() {
    this.a = 10;
    this.method = function() {
        setTimeout(function() {
            console.log(this); // window
        }, 1000);
    }
}
const fun = new Fun();
fun.method();
  1. 由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,所以 call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。


function Fun() {
    this.a = 10;
    this.method = function() {
        setTimeout(() => {
            console.log(this); // Fun {a: 10, method: ƒ}
        }, 1000);
    }
}
const fun = new Fun();
fun.method();

14.3 改变this指向


除了隐式绑定this的方式,还能够通过显示绑定的方式,通过call、apply、bind方式改变this指向,对于这三者的区别后续将有专门的百题斩去阐述,本节主要进行一波简单使用。

  1. call()


call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。


function method(val1, val2) {
    return this.a + this.b + val1 + val2;
}
const obj = {
    a: 1,
    b: 2
};
console.log(method.call(obj, 3, 4)); // 10
  1. apply()


apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。


function method(val1, val2) {
    return this.a + this.b + val1 + val2;
}
const obj = {
    a: 1,
    b: 2
};
console.log(method.apply(obj, [3, 4])); // 10
  1. bind()


bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。


function method(val1, val2) {
    return this.a + this.b + val1 + val2;
}
const obj = {
    a: 1,
    b: 2
};
const bindMethod = method.bind(obj, 3, 4);
console.log(bindMethod); // [Function: bound method]
console.log(bindMethod()); // 10

扩展


  1. call()apply()的区别是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组
  2. bind返回的是一个绑定函数,而call和apply返回的是运行结果;
  3. 多次 bind() 是无效的,只会绑定到第一次调用的对象上;
  4. call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。
相关文章
|
2月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
2月前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
2月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
55 5
|
2月前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
84 1
|
2月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
56 4
|
2月前
|
机器学习/深度学习 自然语言处理 前端开发
前端神经网络入门:Brain.js - 详细介绍和对比不同的实现 - CNN、RNN、DNN、FFNN -无需准备环境打开浏览器即可测试运行-支持WebGPU加速
本文介绍了如何使用 JavaScript 神经网络库 **Brain.js** 实现不同类型的神经网络,包括前馈神经网络(FFNN)、深度神经网络(DNN)和循环神经网络(RNN)。通过简单的示例和代码,帮助前端开发者快速入门并理解神经网络的基本概念。文章还对比了各类神经网络的特点和适用场景,并简要介绍了卷积神经网络(CNN)的替代方案。
183 1
|
2月前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
63 1
|
2月前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
51 1
|
2月前
|
前端开发 JavaScript UED
"前端小技巧大揭秘:JS如何将后台时间戳秒变亲切小时前、分钟前,让用户秒懂,提升互动体验!"
【10月更文挑战第23天】在Web开发中,将后台返回的时间戳转换为“小时前”、“分钟前”、“刚刚”等友好的时间描述是常见需求。本文介绍如何用JavaScript实现这一功能,通过计算当前时间和时间戳的差值,返回相应的描述,提升用户体验。
46 1
|
3月前
|
前端开发 JavaScript 安全
JavaScript前端开发技术
JavaScript(简称JS)是一种广泛使用的脚本语言,特别在前端开发领域,它几乎成为了网页开发的标配。从简单的表单验证到复杂的单页应用(SPA),JavaScript都扮演着不可或缺的角色。
36 3