JavaScript函数中this指向问题详解

this关键字

哪个对象调用函数,函数里面的this指向哪个对象。

**严格模式下:**在全局环境中,this指向的是undefined

**非严格模式下:**在全局环境中,this指向的是window

全局定义的函数直接调用,this => window

function fn(){
	console.log(this);
	// 此时 this 指向 window
}
fn();
// 相当于 window.fn()

对象内部的函数调用,this => 调用者

var obj = {
	fn:function(){
		console.log(this);
	}
}
obj.fn();
// 此时 this 指向 obj

定时器的处理函数,this => window

setTimeout(function(){
	console.log(this);
},0)
// 此时定时器处理函数里面的this 指向 window

事件处理函数,this => 事件源

div.onclick = function(){
	console.log(this);
}
//当你点击 div 的时候,this指向 div

自调用函数,this => window

(function () {
  console.log(this)
})()
// 此时 this 指向 window

改变 this 指向

刚才我们说过的都是函数的基本调用方式里面的 this 指向,我们还有三个方法可以忽略函数本身的 this 指向转而指向别的地方。这三个方法就是 call / apply / bind,是强行改变 this 指向的方法。

  • call/apply/bind附加在函数调用后面使用,可以忽略函数本身的 this 指向
  • call和apply使用时会立即自动调用函数,bind使用时会创建一个函数,但是需要另外去手动调用

call

语法:fn.call(fn 函数体内 this 的指向哪里,arg1, arg2, ...);

作用:调用被绑定的函数fn,指定它的 this 指向并传参

参数:

  • 第一个参数:是 this 指向
  • 其余的参数:需要传入的值,可以是多个,用逗号隔开

使用 call 方法不传参

var num = 666;

function fn() {
  console.log('num = ', this.num);
}

fn.call();  // num = 666

使用 call 方法指定this

var name = 'Rose';
var obj = {name:'Jack'};
function fn(){
	console.log(this.name);
}
fn();	// Rose
fn.call();	// Rose
fn.call(obj);  // jack

使用 call 方法指定this并传参

var name = 'Rack';
var obj = {name:'Jack'};
function fn(a,b){
	console.log(this,a,b);
}
fn(1,2);	// window 1 2
fn.call(obj,1,2);	// obj 1 2
fn(1,3);	// window 1 3

apply

apply方法接受的是一个包含多个参数的数组

语法:fn.apply(fn 函数体内 this 的指向哪里,[arg1, arg2, ...]);

作用:调用被绑定的函数fn,指定它的 this 指向并传参

参数:

  • 第一个参数:this 指向的对象
  • 第二个参数:一个包含多个参数的数组
var obj = {name:'jack'};
function fn(a,b){
	console.log(this,a,b);
}
fn(1,2);	// window 1 2
fn.apply(obj,[1,2]);	// obj 1 2

使用 apply 合并数组

使用push将元素追加到数组中,如果参数是数组,它会将该数组作为单个元素添加,而不是将这个数组内的每个元素添加进去,因此我们最终会得到一个数组内的数组

var arr1 = [1,2];
var arr2 = [3,4];
arr1.push(arr2);
console.log(arr1);	//	[1,2,[3,4]]

concat虽然可以合并数组,但它并不是将元素添加到现有数组,而是创建并返回一个新数组。

var arr1 = [1,2];
var arr2 = [3,4];

var arr3 = arr1.concat(arr2);
console.log(arr1);	// [1,2]
console.log(arr3);	// [1,2,3,4]

如果我们要将元素追加到现有数组又该怎么做?循环?No!这是apply就派上用场了

var arr1 = [1,2];
var arr2 = [3,4];

arr1.push.apply(arr1,arr2);
console.log(arr1);	// [1,2,3,4]

使用 apply 与内置函数连用

/* 找出数组中最大/小的数字 */
var numbers = [5, 6, 2, 3, 7];

var max = Math.max(numbers)
var min = Math.min(numbers)
console.log(min,max);	// NaN NaN

var max = Math.max.apply(null, numbers);
/* 基本等同于 Math.max(numbers[0], ...) 或 Math.max(5, 6, ..) */
var min = Math.min.apply(null, numbers);
console.log(min,max);	// 2 7

bind

语法:fn.bind(fn 函数体内 this 的指向, arg1, arg2, ...);

作用:创建一个新的绑定函数,指定它的 this 指向并传参,必须调用它才会被执行

参数:

  • 第一个参数:this 指向的对象
  • 其余的参数:需要传入的值,可以是多个,用逗号隔开
var obj = {name:'jack'};
function fn(a,b){
	console.log(this,a,b);
}
fn(1,2);	// window 1 2
fn.bind(obj,1,2);	// 未调用不执行
fn.bind(obj,1,3)()	// obj 1 3
var newFn = fn.bind(obj,3,4);
newFn();	// obj 1 4
newFn(5,6);	// obj 3 4

总结

到此这篇关于JavaScript函数中this指向问题的文章就介绍到这了,更多相关JavaScript函数this指向内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Javascript中函数分类&this指向的实例详解

    JS中定义函数的三种方式 通过实例来说明吧 <script> //method1 function fn() { console.log('fn created '); } //method2 var fn2 = function () { console.log('fn2 created'); } //method3 var fn3 = new Function('test', 'console.log(test);'); fn3('fn3 test'); console.dir(fn3);

  • 7道关于JS this的面试题,你能答对几个

    前言 在 JavaScript 中,this 是函数调用上下文.正是由于 this 的行为很复杂,所以在 JavaScript 面试中,总是会问到有关  this 的问题. 做好的准备面试的方法是练习,所以本文针对 this 关键字整理了 7 个有趣的面试. 注意:下面的 JavaScript 代码以非严格模式运行. 1:变量与属性 以下代码输出什么: const object = { message: 'Hello, World!', getMessage() { const message

  • JavaScript 中this指向问题案例详解

    总结 全局环境 ➡️ window 普通函数 ➡️ window 或 undefined 构造函数 ➡️ 构造出来的实例 箭头函数 ➡️ 定义时外层作用域中的 this 对象的方法 ➡️ 该对象 call().apply().bind() ➡️ 第一个参数 全局环境 无论是否在严格模式下,this 均指向 window 对象. console.log(this === window) // true // 严格模式 'use strict' console.log(this === window

  • JavaScript中的this指向问题详解

    前言 相信我,只要记住本文的 7️⃣ 步口诀,就能彻底掌握 JS 中的 this 指向. 先念口诀:箭头函数.new.bind.apply 和 call.欧比届点(obj.).直接调用.不在函数里. 按照口诀的顺序,只要满足前面某个场景,就可以确定 this 指向了. 接下来按照口诀顺序对它们进行详解,文中示例代码都运行在 Chrome 的 Console 控制台中. 文末有精心准备的练习题,用于检验学习成果,别忘了试试~ 1. 箭头函数 箭头函数排在第一个是因为它的 this 不会被改变,所以

  • JavaScript逐点突破系列之this是什么

    了解this 也许你在其他面向对象的编程语言曾经看过this,也知道它会指向某个构造器(constructor)所建立的对象.但事实上在JavaScript里面,this所代表的不仅仅是那个被建立的对象. 先来看看ECMAScript 标准规范对this 的定义: 「The this keyword evaluates to the value of the ThisBinding of the current execution context.」 「this 这个关键字代表的值为当前执行上下

  • JavaScript函数中this指向问题详解

    this关键字 哪个对象调用函数,函数里面的this指向哪个对象. **严格模式下:**在全局环境中,this指向的是undefined **非严格模式下:**在全局环境中,this指向的是window 全局定义的函数直接调用,this => window function fn(){ console.log(this); // 此时 this 指向 window } fn(); // 相当于 window.fn() 对象内部的函数调用,this => 调用者 var obj = { fn:f

  • JavaScript 设计模式中的代理模式详解

    前言: 代理模式,代理(proxy)是一个对象,它可以用来控制对另一个对象的访问. 现在页面上有一个香港回归最想听的金典曲目列表: <ul id="container"> <li>我的中国心</li> <li>东方之珠</li> <li>香港别来无恙</li> <li>偏偏喜欢你</li> <li>相亲相爱</li> </ul> 需要给页面添加

  • python open函数中newline参数实例详解

    目录 问题的由来 具体实例 总结 问题的由来 我在读pythoncsv模块文档 看到了这样一句话 如果 csvfile 是文件对象,则打开它时应使用 newline=‘’.其备注:如果没有指定 newline=‘’,则嵌入引号中的换行符将无法正确解析,并且在写入时,使用 \r\n 换行的平台会有多余的 \r 写入.由于 csv 模块会执行自己的(通用)换行符处理,因此指定 newline=‘’ 应该总是安全的. 我就在思考open函数中的newline参数的作用,因为自己之前在使用open函数时

  • React.memo函数中的参数示例详解

    目录 React.memo?这是个啥? React.memo的第一个参数 父组件 子组件 React.memo优化 React.memo的第二个参数 父组件 子组件 React.memo优化 父组件 子组件 小结 React.memo?这是个啥? 按照官方文档的解释: 如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现.这意味着在这种情况下,React 将跳过渲染组件的操作并直

  • javascript正则表达式中的replace方法详解

    前面的文章我已经介绍了正则的四个基本方法,当时也提到过replace方法 我们来回顾一下replace方法的使用: 先定义一个正则对象:var re=/中间写匹配的条件/; replace():正则匹配字符串,若是匹配成功,将匹配成功的字符串用新的字符串来替换 语法:字符串.replace(re,新的字符串): 举个例子:网络中经常会遇到,不文明的词会被*代替,我们来试一下: <!DOCTYPE> <html> <head> <meta charset='utf-

  • JavaScript面向对象中接口实现方法详解

    本文实例讲述了JavaScript面向对象中接口实现方法.分享给大家供大家参考,具体如下: 接口是面向对象编程的基础,它是一组包含了函数型方法的数据结构,与类一样,都是编程语言中比较抽象的概念.比如生活中的接口,机顶盒,人们利用它来实现收看不同频道和信号的节目,它犹如对不同类型的信息进行集合和封装的设备,最后把各种不同类型的信息转换为电视能够识别的信息.在编程语言中的接口,实际上是不同类的封装并提供统一的外部联系通道,这样其他对象就可以利用接口来调用不同类的成员了. --整理自<jQuery开发

  • C++成员函数中const的使用详解

    目录 修饰入参 值传递 址传递 const修饰入参 修饰返回值 修饰函数 总结 const 在C++中是一个很重要的关键字,其不光可以用来修饰变量,还可以放在函数定义中,这里整理了其在函数中的三个用法. 修饰入参 首先我们要明白在C++中调用函数时存在两种方法,即传递值和传递引用. 值传递 值传递时,调用函数时会创建入参的拷贝,函数中的操作不会对原值进行修改,因此这种方式中不需要使用 const 来修饰入参,因为其只是对拷贝的临时对象进行操作. 址传递 传递地址时函数中的操作实际上是直接对原来的

  • JavaScript/TypeScript中==和===的区别详解

    在JS/TS项目里,除了能看到==操作符来判断两个变量是否相等外,我们还会看到===操作符,这两者有什么区别吗? 先上结论, 对于String, number这些基础类型,==操作符会先把两边的变量进行类型强制转换成相同的类型再比较是否相等:===操作符则不会进行类型转换,而是直接进行比较. 对于array, object这些高级类型,==和 ===是没有区别的,因为它们比较的是 “指针地址” . 对于基础类型和高级类型,== 和 ===是有区别的:==操作符会先把高级类型转换为基础类型之后,进

  • Python函数中的作用域规则详解

    目录 1.简单介绍一下闭包 2.在Python中,并不是任何代码块都能引入新的作用域 3.在Python中,名字绑定在所属作用域中引入新的变量,同时绑定到一个对象. 总结 Python是静态作用域语言,但是它自身是一个动态语言.在Python中变量的作用域是由变量在代码中的位置决定的,与C语言有些相似,但不是完全一样. 在Python 2.0及之前的版本中,Python只支持3种作用域,即局部作用域,全局作用域,内置作用域:在Python2.2中,Python正式引入了一种新的作用域 — 嵌套作

  • JavaScript ES6中CLASS的使用详解

    前言 对于javascript来说,类是一种可选(而不是必须)的设计模式,而且在JavaScript这样的[[Prototype]] 语言中实现类是很蹩脚的. 这种蹩脚的感觉不只是来源于语法,虽然语法是很重要的原因.js里面有许多语法的缺点:繁琐杂乱的.prototype 引用.试图调用原型链上层同名函数时的显式伪多态以及不可靠.不美观而且容易被误解成"构造函数"的.constructor. 除此之外,类设计其实还存在更进一步的问题.传统面向类的语言中父类和子类.子类和实例之间其实是复

随机推荐