进击的 JavaScript(六) 之 this
记得刚开始,我理解 this
的时候 也是云里雾里的,哈哈,希望通过这篇文章,对你有帮助吧。
关于 this
最多的说法,就是:谁调用它,this就指向谁。这话呢,不能说它错了,只能说它讲的不严谨,为什么呢?我们先来了解下 this
的几种绑定规则。
一、默认绑定
默认绑定 发生在全局环境 。
全局环境中,this
默认绑定到 window
。(严格模式下一样)
console.log(this === window);
//true"use strict"; //使用严格模式执行代码
var a = 666;
console.log(this.a)//666
二、隐式绑定
隐式绑定 发生在 方法调用(执行)。
什么是方法呢?通常把 对象的属性值 是函数的,称为方法。
var obj = {fun: function(){}
}//这里obj 对象里 的fun 属性值是个函数, 就把 这个fun 属性称为方法了。
通常,方法调用时,this
隐式绑定到其 所属的对象 上。
var a = "window";var obj = {a: "obj",fun: function(){console.log(this.a);}
}obj.fun();//"obj"
来个难一点的:
var obj1 = {a: "obj1",obj2: {a: "obj2",fun: function(){console.log(this.a);}}
}obj1.obj2.fun();//"obj2"
这里的答案 跟你想的一样吗? 出现这个答案的关键 就是于,fun
函数 在作为对象方法执行时, this
绑定的是它的 所属对象,也就是 obj2
。 而非外层 的 obj1
。
三、隐式绑定丢失
在判断是否是隐式绑定的时候,最容易出问题的地方就是发生在 隐式绑定丢失。
隐式丢失是指被隐式绑定的函数丢失绑定对象,从而绑定到window。这种情况容易出错却又常见。(严格模式下,绑定到undefined)
隐式绑定丢失 一般 发生在 函数独立调用时。
啥是独立调用呢?就是一个简单的函数执行. 函数名的前面没有任何引导内容。
function ff(){};ff(); //独立调用
当函数独立调用(执行)时,this
就会隐式绑定丢失,而绑定到 window
对象上。(非严格模式下)
function fun(){console.log(this === window);
}
fun();
//true
那么严格模式下呢?是指向 undefined
的。
function fun(){"use strict"; //使用严格模式执行代码console.log(this);
}
fun();//undefined
考考你:
var a = "window";var obj = {a: "obj",fun1: function(){console.log(this.a);}
}var fun2 = obj.fun;fun2();
//"window"
判断是否隐式绑定丢失的关键就在于, 判断函数 是否是哪种调用。
上面的例子,关键点就在 最后两行代码。
先看其中的第一行:
var fun2 = obj.fun;
这里把 obj 的fun 方法 赋值给了 一个变量 fun2,这里的 fun 并没有作为对象的方法来执行,因为,fun 方法这里没有执行。
其后:
fun2();
再执行 fun2,它保存着 fun1 方法,这时候执行 fun2(等于fun1) ,但是,它是独立调用。因为,没有作为对象的方法来调用。所以 this 就被指向 window了。
那么怎么解决隐式丢失问题呢?
var a = "window";var obj = {a: "obj",fun: function(){return function(){console.log(this.a);}}
}obj.fun()();//"window"//这里我们想要的是 obj里 a 的值,可是,隐式绑定丢失导致获取到了 window 里 a 的值。
可以基础好的已经知道答案了:
var a = "window";var obj = {a: "obj",fun: function(){var that = this;return function(){console.log(that.a);}}
}obj.fun()();//"obj"
因为 fun
是作为方法调用的,所以 this
绑定到 obj
对象上,因此,我们就可以先用一个变量 that
来保存 this
,然后 在内部的 匿名函数中 使用 that
就可以了。它保存着 上面 this
的绑定对象。
忽然灵机一动,想出个题目,看人家都玩出题,我也试试,哈哈:
var a = "window";function fun(){var a = "fun";return (function(){return this.a;})()
}fun()//“你猜”
这道题中 有立即执行函数、this问题,哈哈,乍一看挺恶心,其实看完上面的,应该可以看出来的。
四、显示绑定
通过call()、apply()、bind()方法把 this
绑定到对象上,叫做显式绑定。对于被调用的函数来说,叫做间接调用。
var a = "window"var obj = {a:"obj",
}function fun(){console.log(this.a);
}fun.call(obj);
//"obj";
这里使用了 call 方法,把fun 中的 this 绑定到 obj 对象上。
javascript内置的一些函数,具有显式绑定的功能,如数组的5个迭代方法:map()、forEach()、filter()、some()、every(),以及创建对象的 Object.create() 函数(后面原型链中会细说),都可以手动绑定this。
大家可以去看下API文档,数组的这几个函数的最后一个参数,就是指定函数内 this 的绑定,如果不指定,则是window
,严格模式下是undefined
。
var a = [1,2,3];a.forEach(function(){console.log(this)
},a);//绑定 this 为 a 这个数组//(3) [1, 2, 3]
//(3) [1, 2, 3]
//(3) [1, 2, 3]
五、new 绑定
如果 使用 new
来创建对象,因为 后面跟着的是构造函数,所以称它为构造器调用。对于this
绑定来说,称为new
绑定。
想知道 构造器调用 中 this
的绑定,就要知道 new
到底做了啥了。
先来个 new 的实现。看不懂不要紧,在后面原型链那篇,还会说的。
function New(proto){ //proto 为传进来的构造函数var obj = {};obj.__proto__ = proto.prototype;proto.apply(obj, Array.prototype.slice.call(argument,1));//你这要看懂这步就行。这里把构造函数里的 this 绑定到了 新的obj 对象上,最后 返回了该新对象,作为实例对象。return obj;
}
所以在使用 new 来创建实例对象时,new 内部把 构造函数的 this 绑定到 返回的新对象 上了。
function Person(name){this.name = name;
}
var c = new Person("zdx");
c.name;
总结: this的四种绑定规则:隐式绑定、隐式绑定丢失、显式绑定和new绑定,分别对应函数的四种调用方式:方法调用、独立调用、间接调用和构造器调用。
附录:
1、关于this绑定 的优先级问题。
简单提一下吧:
new 绑定 > 显示绑定 > 隐式绑定 > 默认绑定 。
2、ES6 中,箭头函数的 this 绑定。
箭头函数内的 this 绑定的 是所属的环境(函数或者对象), 它是固定不变的。
先看下上面的这个例子
var a = "window";var obj = {a: "obj",fun: function(){return function(){console.log(this.a);}}
}obj.fun()();//"window"
上面我们使用 一个变量来保存 this 的绑定,下面我们来用 箭头函数解决问题
var a = "window";var obj = {a: "obj",fun: function(){return () => {console.log(this.a);}}
}obj.fun()();//"obj"
实际上,箭头函数内部是没有this
的,所以,它不能使用 new
构造器调用,call
等显示绑定。所以它内部就是使用了一个变量来保存 箭头函数 所属环境的(函数或者对象) this
。
就相当于:
var a = "window";var obj = {a: "obj",fun: function(){that = this;return function(){console.log(that.a);}}
}obj.fun()();//"obj"
考考你:
var a = "window";var obj = {a: "obj",fun1: function(){return () => {console.log(this.a);}}
}var fun2 = obj.fun1;fun2()();
转载于:https://www.cnblogs.com/zhoudaxiaa/p/9705707.html
进击的 JavaScript(六) 之 this相关推荐
- 进击的 JavaScript 之(七) 原型链
原文链接:周大侠啊 进击的 JavaScript (七) 之 原型链 算是记录一下自己的学习心得吧,哈哈 首先说一下,函数创建的相关知识 在JavaScript中,我们创建一个函数A(就是声明一个函数 ...
- JavaScript(六)
JavaScript(六) 一.正则表达式: 1.每个字符集只能匹配一个字符 2.备选字符集中至少有一个匹配上 ex:[a-zA-Z0-9]所有的应为字母和数字 [\u4e00-\u9fa5]一个汉字 ...
- 进击的JavaScript(对象,继承,单例模式)
1. JavaScript的面向对象 怎么理解js的面向对象编程 面向对象:对外统一提供调用接口的编程思想. 对象: 依靠构造器(constructor)利用原型(prototype)构造出来. ...
- 进击的 JavaScript(四) 之 闭包
上一节说了执行上下文,这节咱们就乘胜追击来搞搞闭包!头疼的东西让你不再头疼! 一.函数也是引用类型的. function f(){ console.log("not change" ...
- 幽情阁--Java8系列之Nashorn JavaScript(六)
本章小宋讲一下JavaScript的引擎Nashorn 目录 Nashorn jjs jjs 交互式编程 jjs传递参数 Java 中调用 JavaScript JavaScript 中调用 Java ...
- Javascript(六十三)网络协议
网络分层的概念 OSI 7层的网络分层 通用 5层网络分层 网络传输协议:网络数据在互联网进行传输,遵从的传输规则 传输层:TCP/UDP port端口号(确定来自哪个软件) 网络层:IP协议 确定传 ...
- ApacheCN JavaScript 译文集(二) 20211123 更新
使用 Meteor 构建单页 Web 应用 零.前言 一.制作 Meteor 应用 二.构建 HTML 模板 三.存储数据和处理集合 四.控制数据流 五.使我们的应用与路由通用 六.保持会话状态 七. ...
- ApacheCN JavaScript 译文集 20211122 更新
JavaScript 编程精解 中文第三版 零.前言 一.值,类型和运算符 二.程序结构 三.函数 四.数据结构:对象和数组 五.高阶函数 六.对象的秘密 七.项目:机器人 八.Bug 和错误 九.正 ...
- 基于HTML+CSS+JavaScript “小味鲜“餐厅网页设计
基于HTML+CSS+JavaScript "小味鲜"餐厅网页设计 每博一文案 师父说"生活中的负能大多来于圈子里的抱怨",有时候,你不想做别人情绪的垃圾桶. ...
最新文章
- 获得TADIR-OBJECT全部的entry list
- 管理多个Java安装
- 从中师到博士,我用了22年...
- ECCV 2020 | 微软亚洲研究院精选论文摘录
- python逢7跳过_python实现逢七拍腿小游戏的思路详解
- WindowsServer2012 DFS配置出错原因
- 第一章 微服务网关 - 入门
- ggplot2分面柱状图柱子比例一致_R语言柱状图
- 工程学导论1---3章习题与思考题
- 《嵌入式C编程:PIC单片机和C编程技术与应用》一导读
- [python爬虫] Selenium爬取新浪微博内容及用户信息
- 计算机学情分析案例,小学信息技术课学情分析
- windows_帮助文档【.CHM电子书】打开显示空白解决办法
- 边境的悍匪—机器学习实战:第十四章 使用卷积神经网络的深度计算机视觉
- 【RocketMQ】从零搭建一套RocketMQ监控(rocketmq-exporter + Prometheus + Grafana)
- 平板电脑win10 android比较好,华为MateBook名不副实!Win10平板电脑最合适
- Rime输入法小狼毫皮肤配色
- 超简单的页眉页脚设置(摘要、目录页眉不同、页脚页码连续)
- 2<<3是什么意思?
- 建一个手机网站到底需要多少钱
热门文章
- Using Markov Chains for Android Malware Detection
- 深入理解Android的startservice和bindservice
- 工作单元php,php – 无法从工作单元测试用例构建最简单的套件
- linux进程卡住_鸿蒙系统,Linux? Android?
- spring-mybatis.xml 访问html5,Spring mvc无xml配置及利用JdbcTemplate访问数据库
- mac 当前文件夹打开终端_Mac上的这些实用你技巧,你知道几个?
- 窗口位置按钮取消_梦幻西游:五开玩家都是怎样摆放窗口的
- 文本分类入门(四)训练Part 1
- 数学之美系列之一:统计语言模型 (Statistical Language Models)
- JZOJ__Day 1:【普及模拟】PLES