作用域链和函数内部this指向问题以及bind、call、apply方法
作用域链和函数内部this指向问题以及bind、call、apply方法
作用域链
作用域是相对于变量而言的, 其意义就在与查找变量(确定变量的来处, 变量是否可以访问到, 确定变量在当前位置是否可以取到值)
JS分函数作用域和全局作用域JS变量又遵循就近使用的原则- 首先在使用该变量的当前作用域查找 , 如果当前作用域声明了这个变量,就可以确定结果;如果没有查找到,进入步骤2
- 查找当前作用域的上级作用域,也就是当前函数的上级函数,看看上级函数中有没有声明
- 再查找上级函数的上级函数,直到全局作用域为止
- 如果全局作用域中也没有,我们就认为这个变量未声明
xxx变量 is not defined
如何确定函数作用域的上一级作用域
函数的上一次作用域取决于函数声明时的位置,而不是函数调用时的位置。
函数就声明在全局作用域内
<script>
function fn(callback){
var age=18;
callback()
} fn(function(){
console.log(age); //age is not defined
//分析:age变量:
//1、查找当前作用域:并没有
//2、查找上一级作用域:全局作用域 (此时函数就声明在全局作用域内)
//3、此时age变量就获取不到fn函数内部的age变量
//看上一级作用域,不是看函数在哪里调用,而是看函数在哪里编写,函数声明在全局,它的上一级作用域就是全局作用域。
//-->因为这种特别,我们通常会把作用域说成是:词法作用域
})
</script>
函数声明在其它的函数内 (闭包就是个典型案例)
<script>
function fn(){
var a=5;
return function(){
a++;
console.log(a); //a变量肯定是可以访问的
}
}
var f1=fn(); //f1指向匿名函数
f1(); //6
f1(); //7
f1(); //8
//分析:a变量:
//1、查找当前作用域:并没有
//2、查找上一级作用域:fn函数作用域 (此时函数就声明在fn函数内) //-->一般认为函数执行完毕,变量就会释放,但是此时由于js引擎发现匿名函数要使用a变量,所以a变量并不能得到释放,而是把a变量放在匿名函数可以访问到的地方去了
//-->a变量存在于f1函数可以访问到的地方,当然此时a变量只能被f1函数访问
</script>
函数内部的this指向问题(箭头函数不适用)
函数的4种调用方式
普通函数调用的方式
<script>
var age = 18; //该age声明在全局作用域下,其就会被挂载到window对象上,即window.age=18
var p = {
age: 15,
say: function () {
console.log(this.age); //this指向window
}
}
var s1 = p.say //s1 = function () {console.log(this.age);}
s1(); //函数调用, 结果为 18
</script>
方法的调用
<script>
var age = 18; //该age声明在全局作用域下,其就会被挂载到window对象上,即window.age=18
var p = {
age: 15,
say: function () {
console.log(this.age); //this指向p对象
}
}
p.say() //结果为15 //p.say获取的就是p对象内部的say方法,然后方法后+()就是方法的调用。
</script>
new调用(构造函数)
<script>
var age = 18;
var p = {
age: 15,
say: function () {
console.log(this.age);
//此时this指向构造函数new出来的实例,而实例中并没有初始化age属性
}
}
new p.say() //构造函数调用, 结果为undefined
</script>
<script>
var age = 18;
var p = {
age: 15,
say: function (age) {
this.age = age
console.log(this.age);
}
}
new p.say(22) //构造函数调用, 结果为22
</script>
上下文方式(call、apply、bind)
<script>
var length = 21; //window.length = 21
function f1() {
console.log(this.length);
}
f1.call([1, 3, 5]) //结果为3,此时this指向[1,3,5]数组
f1.apply(this) //结果为21,此时this指向window
f1.call(5) //undefinde , 此时this指向 Number,其没有length属性
f1.bind(this)() //结果为21
//bind方法只改变函数f1内部this指向,而不会让函数执行,想让其执行,需要在后面手动调用+()
</script>
bind、call、apply共同点和区别
- 三个方法都可以改变函数内部this指向
- bind和call、apply的区别是,bind方法不会让函数执行,而call、apply的调用会让函数也跟着执行
- call和apply的区别就在与给函数传参的方式不同
- call(this指向对象, 参数1,参数2,参数3) 参数以逗号分隔,依次排下去
- apply(this指向对象, [参数1,参数2,参数3]) 参数包裹在一个数组中
作用域链和函数内部this指向问题以及bind、call、apply方法的更多相关文章
- this的指向问题、bind/call/apply改变this指向
this的指向问题 全局作用域下的this指向 无论是否是严格模式,全局作用域下的this始终指向window 函数内部的this 严格模式下: function test() { 'use stri ...
- [译]JavaScript:函数的作用域链
原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...
- python中函数的嵌套和作用域链
1.三元运算if条件成立的结果 if 条件 else 条件不成立的结果例如: a=20 b=10 c=a if a>b else b print(c) 2.命名空间 全局命名空间:创建的存储“变 ...
- JS中的函数声明和函数表达式的区别,即function(){}和var function(){},以及变量提升、作用域和作用域链
一.前言 Uncaught TypeError: ... is not a function function max(){}表示函数声明,可以放在代码的任何位置,也可以在任何地方成功调用: var ...
- 从函数作用域和块级作用域看javascript的作用域链
在ES6之前,javascript只有全局作用域和函数作用域.所谓作用域就是一个变量定义并能够被访问到的范围.也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这 ...
- 函数的作用域、作用域链以及return关键字
1.作用域 全局作用域:在函数外部使用var关键字定义的变量 局部作用域:在函数内部使用var关键字定义的变量 特点 (1)局部变量无法直接影响全局变量 (2)在局部作用域中可以使用全局作用 ...
- javascript篇-----函数作用域,函数作用域链和声明提前
在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于 ...
- js修改函数内部的this指向(bind,call,apply)
js修改函数内部的this指向 在调用函数的时候偶尔在函数内部会使用到this,在使用this的时候发现并不是我们想要指向的对象.可以通过bind,call,apply来修改函数内部的this指向. ...
- 改变JavaScript中函数的内部this指向!
改变JavaScript中函数的内部this指向! 第一种方法 call call 可以 调用函数 + 改变函数内的this指向! var obj = { name: 'lvhang' } funct ...
随机推荐
- ACM-自学之旅
分类 知识清单 数据结构 链式前向星 树状数组 线段树 线段树的区间合并 基于ST表格的RMQ 图论 最近公共祖先 树的直径.树的重心与树的点分治 树的最小支配集,最小点覆盖与最大独立集 求无向连通图 ...
- hbase-default.xml(Hbase 默认参数翻译)
hbase.tmp.dir \({java.io.tmpdir}/hbase-\){user.name} 本地文件系统上的临时目录.将'/tmp'改为其他可以持久保存文件的位置,通常能够解决java. ...
- linux搭建FastDFS文件服务器
本文主要介绍在linux服务器如何搭建FastDFS文件服务器.大概分为9个步骤,由于内容较为繁琐.下面带你入坑! 首先简单介绍一下FastDFS是淘宝资深架构师余庆老师主导开源的一个分布式文件系统, ...
- [Android] Android 手机下 仿 今日头条 新闻客户端
利用一个月的时间,自学了 Android 开发 ,为了检验学习成果,特意 开发了这个 仿 今日头条 新闻客户端 AppNews 包括图文新闻+视频新闻+图片新闻 预览演示如下: 功能说明: 1)底部 ...
- docker自定制镜像
概述 很多情况下我们需要自定制镜像,如果自定制过程中需要下载配置很多包,而且这些包之间还有依赖关系,那么如果我们手动去操作的话就会很麻烦,正确的做法是把操作的命令封装到一个文件里,然后直接执行这个文件 ...
- 【转载】VS写汇编程序01:VS2015配置汇编语言开发环境
https://blog.csdn.net/qq_28249373/article/details/83475107
- linxu上安装mongodb3.6实战
根据linux 版本到官网下载对应mongodb版本 查看服务器版本:cat /proc/version 查看linux发行版本:cat /etc/redhat-release 我用的阿里云服务器,对 ...
- 分布式系列九: kafka
分布式系列九: kafka概念 官网上的介绍是kafka是apache的一种分布式流处理平台. 最初由Linkedin开发, 使用Scala编写. 具有高性能,高吞吐量的特定. 包含三个关键能力: 发 ...
- Spring框架中的org.springframework.context.annotation.Import注解类
@Import注解的作用和在使用spring的xml配置时用到的<import/>类似.但应注意是@Import在使用时必须要保证能被IOC容器扫描到,所以通常它会和@Configurat ...
- NB-IoT是怎么工作的,是否支持基站定位?【转】
转自:http://www.elecfans.com/iot/779658.html 根据我国无线电管理相关要求,明确NB-IoT系统基站应到到属地无线电管理机构办理设台审批,领取无线电台执照.同时, ...