[转载]this 指向详细解析(箭头函数)
本文转自:http://www.cnblogs.com/dongcanliang/p/7054176.html
为了以后更方便的查看,便做了转载
前言
this 指向问题是入坑前端必须了解知识点,现在迎来了ES6时代,因为箭头函数的出现,所以感觉有必要对 this 问题梳理一下,遂有此文
在非箭头函数下, this 指向调用其所在函数的对象,而且是离谁近就是指向谁(此对于常规对象,原型链, getter & setter等都适用);构造函数下,this与被创建的新对象绑定;DOM事件,this指向触发事件的元素;内联事件分两种情况,bind绑定, call & apply 方法等, 容以下一步一步讨论。箭头函数也会穿插其中进行讨论。
全局环境下
在全局环境下,this 始终指向全局对象(window), 无论是否严格模式;
console.log(this.document === document); // true// 在浏览器中,全局对象为 window 对象: console.log(this === window); // truethis.a = 37; console.log(window.a); // 37
函数上下文调用
函数直接调用
普通函数内部的this分两种情况,严格模式和非严格模式。
严格模式下,this 的值默认为全局对象window
function f1(){return this; }f1() === window; // true
非严格模式, this的值为undefined
function f2(){"use strict"; // 这里是严格模式return this; }f2() === undefined; // true
对象中的this
对象内部方法的this指向调用这些方法的对象,
- 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关。
- 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
//1 var o = {prop: 37,f: function() {return this.prop;} }; console.log(o.f()); //37 var a = o.f; console.log(a()): //undefinedvar o = {prop: 37};function independent() {return this.prop; }o.f = independent;console.log(o.f()); // logs 37//2 o.b = {g: independent,prop: 42 }; console.log(o.b.g()); // logs 42
原型链中this
原型链中的方法的this仍然指向调用它的对象,与以上讨论一致;看个例子,
var o = {f : function(){ return this.a + this.b; } }; var p = Object.create(o); p.a = 1; p.b = 4;console.log(p.f()); // 5
可以看出, 在p中没有属性f,当执行p.f()时,会查找p的原型链,找到 f 函数并执行,但这与函数内部this指向对象 p 没有任何关系,只需记住谁调用指向谁。
以上对于函数作为getter & setter 调用时同样适用。
构造函数中this
构造函数中的this与被创建的新对象绑定。
注意:当构造器返回的默认值是一个this引用的对象时,可以手动设置返回其他的对象,如果返回值不是一个对象,返回this。
function C(){this.a = 37; }var o = new C(); console.log(o.a); // logs 37function C2(){this.a = 37;return {a:38}; }var b = new C2(); console.log(b.a); // logs 38
以上两个例子内部的this都指向对象o, 看到这里的你不妨在控制台执行下以上代码,看看对象 o 和 b ,这些是属于构造函数的内容了,此处不多做介绍。(C2函数中的this.a = 37 对整个过程完全没有影响的, 可以被忽略的)。
call & apply
当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它。
例子:
function add(c, d){return this.a + this.b + c + d; }var o = {a:1, b:3};add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34function tt() {console.log(this); } // 返回对象见下图(图1) tt.call(5); // Number {[[PrimitiveValue]]: 5} tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
bind 方法
bind方法在ES5引入, 在Function的原型链上, Function.prototype.bind
。通过bind方法绑定后, 函数将被永远绑定在其第一个参数对象上, 而无论其在什么情况下被调用。
function f(){return this.a; }var g = f.bind({a:"azerty"}); console.log(g()); // azertyvar o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty
DOM 事件处理函数中的 this & 内联事件中的 this
DOM事件处理函数
- 当函数被当做监听事件处理函数时, 其 this 指向触发该事件的元素 (针对于addEventListener事件)
// 被调用时,将关联的元素变成蓝色function bluify(e){//在控制台打印出所点击元素console.log(this);//阻止时间冒泡 e.stopPropagation();//阻止元素的默认事件 e.preventDefault(); this.style.backgroundColor = '#A5D9F3';}// 获取文档中的所有元素的列表var elements = document.getElementsByTagName('*');// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色for(var i=0 ; i<elements.length ; i++){elements[i].addEventListener('click', bluify, false);}
以上代码建议在网页中执行以下,看下效果。
内联事件
内联事件中的this指向分两种情况:
- 当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素
- 当代码被包括在函数内部执行时,其this指向等同于 ****函数直接调用****的情况,即在非严格模式指向全局对象window, 在严格模式指向undefined
页面的代码块
在浏览器内显示三个按钮
依次点击上边的三个按钮后在控制台的输出结果,
建议自己操作一遍以便于更好的理解。
setTimeout & setInterval
对于延时函数内部的回调函数的this指向全局对象window(当然我们可以通过bind方法改变其内部函数的this指向)
看下边代码及截图
//默认情况下代码 function Person() { this.age = 0; setTimeout(function() {console.log(this);}, 3000); }var p = new Person();//3秒后返回 window 对象 ============================================== //通过bind绑定 function Person() { this.age = 0; setTimeout((function() {console.log(this);}).bind(this), 3000); }var p = new Person();//3秒后返回构造函数新生成的对象 Person{...}
箭头函数中的 this
由于箭头函数不绑定this, 它会捕获其所在(即定义的位置)上下文的this值, 作为自己的this值,
- 所以 call() / apply() / bind() 方法对于箭头函数来说只是传入参数,对它的 this 毫无影响。
- 考虑到 this 是词法层面上的,严格模式中与 this 相关的规则都将被忽略。(可以忽略是否在严格模式下的影响)
因为箭头函数可以捕获其所在上下文的this值 所以
function Person() { this.age = 0; setInterval(() => {// 回调里面的 `this` 变量就指向了期望的那个对象了this.age++;}, 3000); }var p = new Person();
以上代码可以得到我们所以希望的值,下图可以看到,在setTimeout中的this指向了构造函数新生成的对象,而普通函数指向了全局window对象
var adder = {base : 1,add : function(a) {var f = v => v + this.base;return f(a);},addThruCall: function inFun(a) {var f = v => v + this.base;var b = {base : 2};return f.call(b, a);} };console.log(adder.add(1)); // 输出 2 console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3,其内部的this并没有因为call() 而改变,其this值仍然为函数inFun的this值,指向对象adder
bind() & apply() 读者可以自行测试
对于是否严格模式示例代码(可以复制进控制台进行验证)
var f = () => {'use strict'; return this}; var p = () => { return this}; console.log(1,f() === window); console.log(2,f() === p()); //1 true //2 true
以上的箭头函数都是在方法内部,总之都是以非方法的方式使用,如果将箭头函数当做一个方法使用会怎样呢?
上例子
var obj = {i: 10,b: () => console.log(this.i, this),c: function() {console.log( this.i, this)} } obj.b(); // undefined window{...} obj.c(); // 10 Object {...}
可以看到,作为方法的箭头函数this指向全局window对象,而普通函数则指向调用它的对象
以上为个人学习整理内容, 文中例子参考MDN, 欢迎交流学习
参考文献
this - JavaScript | MDN
箭头函数 - JavaScript | MDN
转载于:https://www.cnblogs.com/liugx/p/9106402.html
[转载]this 指向详细解析(箭头函数)相关推荐
- this 指向详细解析(箭头函数)
this 指向详细解析(箭头函数) 前言 this 指向问题是入坑前端必须了解知识点,现在迎来了ES6时代,因为箭头函数的出现,所以感觉有必要对 this 问题梳理一下,遂有此文 在非箭头函数下, t ...
- this:它到底指向哪里!箭头函数的this又是啥?
文章目录 JavaScritp 中的 this 总结一句话(永真给的信) 默认绑定(指向少主window) 严格模式(变若之子) 隐式绑定(苇名弦一郎) 隐式丢失(赤鬼 + 鬼庭形部雅孝) 显式绑定( ...
- 箭头函数的this指向谁_高阶函数
NodeJS 系列文章,本篇是第一篇,首先,预计将后续高频使用逻辑串一遍,依次是高阶函数,promise以及事件机制.本篇主要是高阶函数. call.bind.apply call.apply 都是改 ...
- c语言的point函数,C语言中friend友元函数详细解析
C语言中friend友元函数详细解析 友元函数是可以直接访问类的私有成员的非成员函数.它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字frien ...
- 普通函数和箭头函数中的this指向
普通函数的this指向Window function a(){console.log(this) } a() //Window Dom元素绑定事件时的this,句柄里的 this 值是该元素的引用 d ...
- JavaScript箭头函数的使用和this指向
01-箭头函数的基本使用 普通定义函数的方式:function const aaa = function() {} // es6箭头函数 const aaa = () => {} 对象字面量定义 ...
- 网易试题——关于箭头函数与this和arguments的关系
昨天做试题的时候遇到了这个题目 var a = 1;function fn1() {console.log(this.a)}const fn2 = () => {console.log(this ...
- js 中的this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解
壹 ❀ 引 工具猴-免费在线工具-在线工具箱- 可以说this与闭包.原型链一样,属于JavaScript开发中老生常谈的问题了,百度一搜,this相关的文章铺天盖地.可开发好几年,被几道this题安 ...
- 五种绑定彻底弄懂this,默认绑定、隐式绑定、显式绑定、new绑定、箭头函数绑定详解
壹 ❀ 引 可以说this与闭包.原型链一样,属于JavaScript开发中老生常谈的问题了,但开发好几年,依然被几道this指向题安排明明白白的人应该不在少数.对于初学者而言,this概念抽象,变化 ...
- ES6 箭头函数大起底:熟知这几个特点让你少踩很多坑
作者简介: 李中凯 八年多工作经验 前端负责人, 擅长JavaScript/Vue. 掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b58006b1b8666/po ...
最新文章
- 深度学习编译器Data Flow和Control Flow
- 几个非常低调的公众号!但副业月入早已过3万...
- 理解C#值类型与引用类型(摘录)
- JZOJ__Day 10:【普及模拟】【USACO】iCow播放器
- js粘贴板为什么获取不到图片信息_图床+typora,告别markdown中关于图片的困惑
- android 带弧形背景,[Android日常]绘制弧形渐变背景
- 前端学习(2753):创建新页面和页面配置
- Java CXF介绍与实例
- bzoj 2428: [HAOI2006]均分数据
- STM32重上电后,HAL_GetDEVID返回0
- udp java 实例_udp例子,javaudp简单实例分享
- EL表达式和jstl的简单应用
- Move: 一门面向资产的编程语言
- img元素实现图片裁切放大
- iOS开发 DarkMode 暗黑模式
- 五大手机测试鸿蒙,厉害了!鸿蒙系统完成100万部手机测试,兼容多个国产品牌手机!...
- ORCALE DDL,DML,DQL命令
- 嵌入式linux学习路线,嵌入式开发视频教程
- 三星s6如何打开位置服务器,三星手机如何定位对方手机所在位置(如何知道对方手机位置)...
- 计算机网络 一、 IP地址,域名,DNS
热门文章
- websphere html 缓存,如何清除WebSphere类缓存
- rtk手簿Android代码,中海达rtk手机测量软件(Hi-Survey Road)
- python django企业固定资产管理系统pycharm项目源码lw
- 一文读懂:DNA甲基化的作用及各种高通量检测方法比较
- 3.	Zigbee应用程序框架开发指南 - 应用程序框架目录结构
- win7计算机共享设置密码,如何为Win7旗舰系统的共享文件夹设置密码
- 数字孪生智慧交通仿真推演解决方案
- php中thead怎么居中,html thead标签怎么用
- org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates
- 3V转1.8V三极管稳压IC