Javascript中的this(七)
一、为什么要用this
通过this可以在不同的上下文对象中重复使用函数
二、this是什么
this就是我们说的执行上下文(包含调用栈(哪里被调用)、函数的调用方式、传入的参数等信息)
三、this的绑定规则
1、默认绑定
当函数调用没有引用对象时,默认this指向全局对象
2、隐式绑定
this指向函数的调用者
3、显示绑定
通过apply/call、bind绑定
4、new绑定
this指向new出来的对象
5、es6的箭头函数,this指向第一个不是箭头函数的函数的父作用域
四、测验
1、回顾一下闭包的一个例子,搞懂词法作用域的使用
example1:
var fun;
var a = 1;
function fn() {
var a = 2;
function foo() {
console.log(a);
} fun = foo;
} function fun2 () {
var a = 3;
fun()
} fn()
fun2()
foo的引用返回给了一个变量fun,fun是全局变量,一直存在内存中,fn执行完,内存不会被销毁,因为内部的变量foo还被引用着,再调用fun2,对foo中的a进行RHS查询,查找到当前词法作用中的a = 2,所以输出为2.
example1输出结果2
example2:
var fun;
var a = 1;
function fn() {
function foo() {
console.log(a);
} fun = foo;
} function fun2 () {
var a = 3;
fun()
} fn()
fun2()
输出结果1
闭包只不过是可以让函数的词法作用域一直被引用着,让函数在执行完之后其作用域中的变量仍然能够再被使用。
回顾一下这句话:
动态作用域的作用域链基于调用栈,而不是代码的作用域嵌套;
this机制让作用域有了动态作用域的特点;
js中实质上没有动态作用域,只有词法作用域(什么是词法作用域?词法作用域是一套js引擎如何查找变量以及会在何处查找到变量的规则)
function t() {
console.log(b)
}
function h() {
var b = 4;
t()
}
var b = 3;
h()
输出结果3
什么叫基于调用栈? 基于调用栈就应该是在查找变量时,如果没有查找到变量会基于调用栈向上一层一层的查找,直到查找到或查找至全局作用域。
下面的例子也很清晰的表明了查找变量时,是基于词法作用域的,并不是基于调用栈。(对于详细的词法作用域解释可以看我写的作用域篇)
var a = 0
function bar1() {
var a = 1;
console.log('bar1 ',a)
bar2()//调用位置
} function bar2() {
console.log('bar2 ', a)//调用栈 bar1=>bar2
bar3()//调用位置
} function bar3() {
//调用栈 bar1=>bar2=>bar3
console.log('bar3 ', a)//调用位置
} bar1()
输出:
bar1 1
bar2 0
bar3 0
2、this的默认绑定规则
默认绑定,无论在哪里调用函数,没有引用对象时this指向全局对象:
function foo() {
console.log(this.a)
}
var a=2;
(function() {
var a = 3;
foo()
})()
输出2
3、this的隐式绑定规则,可能会出现的绑定对象丢失的情况
this指向函数的直接调用者,且只有在上一层调用才起作用
function foo() {
console.log(this.a)
}
function foo2(fn) {
fn()
}
var obj = {
a: 2,
foo: foo
}
var a = "global"
obj.foo() //2
foo2(obj.foo)//global
obj.foo当参数传给foo2,参数fn引用着函数foo,调用fn,this又遵循默认绑定,this指向全局对象。
4、显示绑定
显示绑定就是通过apply/call、bind来改变函数的this指向;
当给apply/call第一个参数传递null或undefined的时,默认this指向全局对象;
典型应用场景,创建一个包裹函数,接受参数并返回值。
function add (param) {
return this.a + param
}
var obj = {
a: 3
}
var bar = function() {
add.apply(obj)
}
bar(2)
//5
bind方法实现:
function add (param) {
return this.a + param
}
var obj = {
a: 3
}
function bind(fn, obj) {
return function() {
return fn.apply(obj, arguments)
}
}
var f = bind(add, obj)
f(2)
//5
5、new绑定
五、关于this绑定规则的优先级
显示绑定>隐式绑定
new绑定>隐式绑定
硬绑定>隐式绑定
硬绑定>new绑定
参考学习资料:
《你不知道的javascript》上
Javascript中的this(七)的更多相关文章
- javascript中的真假值、数据类型判断以及+的特殊用法
一.javascript中的假值 jQuery中拥有一组数量奇大的假值,包括 0,NaN(非数),''(空字符串),false,null,undefined 这些值在if判断中全部等于假,但这些值彼此 ...
- JavaScript中七种数据类型·中·一
Standing on Shoulders of Giants; 说到JavaScript里的类型很容易就让人想起 42和"42",分别是string型和number型,但是他们可 ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
- Javascript中的valueOf与toString
基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...
- 让你分分钟学会Javascript中的闭包
Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...
- JavaScript中的正则表达式(终结篇)
JavaScript中的正则表达式(终结篇) 在之前的几篇文章中,我们了解了正则表达式的基本语法,但那些语法不是针对于某一个特定语言的.这篇博文我们将通过下面几个部分来了解正则表达式在JavaScri ...
- 谈谈javascript中的日期Date对象
一.日期对象 在javascript中并没有日期型的数据类型,但是提供了一个日期对象可以操作日期和时间. 日期对象的创建: new Date();二.将日期对象转换为字符串 将日期对象转换为字 ...
- 深入理解JavaScript中的==运算符
原文章地址 在详细介绍图1中的每个部分前,我们来复习一下JS中关于类型的知识: JS中的值有两种类型:基本类型.对象类型. 基本类型包括:Undefined.Null.Boolean.Number和S ...
- javascript中关于数组的一些鄙视题
一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...
- 深入理解JavaScript中创建对象模式的演变(原型)
深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...
随机推荐
- CF1132.Educational Codeforces Round 61(简单题解)
A .Regular Bracket Sequence 题意:给定“((” , “()” , “)(”, “))”四种,问是否可以组成合法括号匹配 思路:设四种是ABCD,B可以不用管,而C在A或 ...
- SQLI DUMB SERIES-3
less3 输入?id=1' 说明输入的id旁边加了单引号和括号('id'),直接在1后面加入“ ') ”,闭合前面的单引号和括号. 方法同less1相同. 例如:查询PHP版本和数据库名字 ?id= ...
- tomcat7简单优化
生产环境下我们不应该使用root用户开启tomcat服务,所以为了安全起见,我们创建一个用户tomcat useradd tomcat passwd tomcat(密码也设为tomcat) 编辑tom ...
- day 47 html 学习 css 学习
前端基础之CSS CSS实例 每个CSS样式由两个组成部分:选择器和声明.声明又包括属性和属性值.每个声明之后用分号结束. CSS(Cascading Style Sheet,层叠样式表)定义如何显示 ...
- c#实现RGB字节数组生成图片
我是要用c#来实现,现在已经知道了rgb数组,那么如何快速生成一张图片呢? 其实这个话题并不局限于是rgb字节数组的顺序,只要你能对于上表示红.绿.蓝的值,就可以生成图片.知道了原理,做什么都简单了. ...
- 重写( override)and 重载(overload)
重写override:是子类对父类的允许访问的方法的实现过程的重新编写,名字,返回值和形参都不能改变,即外壳不变,内心更改 重载overload:同一个类里面的方法,名字相同而参数不同,返回值可以相同 ...
- ML(附录3)——过拟合与欠拟合
过拟合与欠拟合 我们希望机器学习得到好的模型,该模型能够从训练样本中找到一个能够适应潜在样本的普遍规律.然而,如果机器学习学的“太好”了,以至把样本的自身特点当作潜在样本的一般特性,这就使得模型的泛化 ...
- TestNG.xml参数配置-如何控制部分执行@test方法
如果在methods中标识了@test的方法,也可以在method中通过include和exclude来控制需要执行哪些方法 <include name="testMethod1&qu ...
- Centos6.8 Mysql5.6 安装配置教程(转)
准备Mysql文件: 方式一:wget url(mysql下载地址); 方式二:从官网下载mysql,上传至centos(小编使用的Nodepad++的NppFTP具体做法请百度); 检查之前安装 ...
- slice.indices()/collections.Counter笔记
关于slice.indices() >>> help(slice) Help on class slice in module builtins: class slice(objec ...