JS核心系列:浅谈函数的作用域
一、作用域(scope)
所谓作用域就是:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。
function scope(){ var foo = "global"; if(window.getComputedStyle){ var a = "I'm if"; console.log("if:"+foo); //if:global } while(1){ var b = "I'm while"; console.log("while:"+foo);//while:global break; } !function (){ var c = "I'm function"; console.log("function:"+foo);//function:global }(); console.log( foo,//global a, // I'm if b, // I'm while c // c is not defined ); } scope();
(1)scope函数中定义的foo变量,除过自身可以访问以外,还可以在if语句、while语句和内嵌的匿名函数中访问。 因此,foo的作用域就是scope函数体。
(2)在javascript中,if、while、for 等代码块不能形成独立的作用域。因此,javascript中没有块级作用域,只有函数作用域。
但是,在JS中有一种特殊情况:
如果一个变量没有使用var声明,window便拥有了该属性,因此这个变量的作用域不属于某一个函数体,而是window对象。
function varscope(){ foo = "I'm in function"; console.log(foo);//I'm in function } varscope(); console.log(window.foo); //I'm in function
二、作用域链(scope chain)
所谓作用域链就是:一个函数体中嵌套了多层函数体,并在不同的函数体中定义了同一变量, 当其中一个函数访问这个变量时,便会形成一条作用域链(scope chain)。
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(){ console.log(foo); } second(); //second third(); //first } first();
ond时,JS引擎会将second的作用域放置链表的头部,其次是first的作用域,最后是window对象,于是会形成如下作用域链:
second->first->window, 此时,JS引擎沿着该作用域链查找变量foo, 查到的是"second"
当执行third时,third形成的作用域链:third->first->window, 因此查到的是:"frist"
特殊情况:with语句
JS中的with语句主要用来临时扩展作用域链,将语句中的对象添加到作用域的头部。with语句结束后,作用域链恢复正常。
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(obj){ console.log(foo); //first with (obj){ console.log(foo); //obj } console.log(foo); //first } var obj = {foo:'obj'}; third(obj); } first();
在执行third()时,传递了一个obj对象,obj中有属性foo, 在执行with语句时,JS引擎将obj放置在了原链表的头部,于是形成的作用域链如下:
obj->third->first->window, 此时查找到的foo就是obj中的foo,因此输出的是:"obj", 而在with之前和之后,都是沿着原来的链表进行查找,从而说明,在with语句结束后,作用域链已恢复正常。
三、this 关键字
在一个函数中,this总是指向当前函数的所有者对象,this总是在运行时才能确定其具体的指向, 也才能知道它的调用对象。
这句话总结了关于this的一切,切记,切记,切记!(ps:重要的事情说三遍!)
window.name = "window"; function f(){ console.log(this.name); } f();//window var obj = {name:'obj'}; f.call(obj); //obj
在执行f()时,此时f()的调用者是window对象,因此输出"window"
f.call(obj) 是把f()放在obj对象上执行,相当于obj.f(),此时f中的this就是obj,所以输出的是"obj"
四、实战应用
code1:
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ return function(){ return this.foo; }; } }; var f = obj.getFoo(); f(); //window
code2:
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ var that = this; return function(){ return that.foo; }; } }; var f = obj.getFoo(); f(); //obj
code1和code2是对this和scope最好的总结,如果对于运行结果有疑惑,欢迎讨论!
代码解析:
code1: 执行var f = obj.getFoo()返回的是一个匿名函数,相当于: var f = function(){ return this.foo; } f() 相当于window.f(), 因此f中的this指向的是window对象,this.foo相当于window.foo, 所以f()返回"window" code2: 执行var f = obj.getFoo() 同样返回匿名函数,即: var f = function(){ return that.foo; } 唯一不同的是f中的this变成了that, 要知道that是哪个对象之前,先确定f的作用域链:f->getFoo->window 并在该链条上查找that,此时可以发现that指代的是getFoo中的this, getFoo中的this指向其运行时的调用者,从var f = obj.getFoo() 可知此时this指向的是obj对象,因此that.foo 就相当于obj.foo,所以f()返回"obj"

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

typedef struct 在 C 语言中用于创建结构体类型别名,简化结构体使用。它通过指定结构体别名将一个新的数据类型作为现有结构体的别名。优点包括增强可读性、代码重用和类型检查。注意:在使用别名前必须定义结构体,别名在程序中必须唯一并且仅在其声明的作用域内有效。

Java 中的变量期望值异常可以通过以下方法解决:初始化变量;使用默认值;使用 null 值;使用检查和赋值;了解局部变量的作用域。

JavaScript 闭包的优点包括保持变量作用域、实现模块化代码、延迟执行和事件处理;缺点包括内存泄漏、增加了复杂性、性能开销和作用域链影响。

C++ 中的 #include 预处理器指令将外部源文件的内容插入到当前源文件中,以复制其内容到当前源文件的相应位置。主要用于包含头文件,这些头文件包含代码中需要的声明,例如 #include <iostream> 是包含标准输入/输出函数。

C++智能指针的生命周期:创建:分配内存时创建智能指针。所有权转移:通过移动操作转移所有权。释放:智能指针离开作用域或被明确释放时释放内存。对象销毁:所指向对象被销毁时,智能指针成为无效指针。

1、 SUM函数,用于对一列或一组单元格中的数字进行求和,例如:=SUM(A1:J10)。2、AVERAGE函数,用于计算一列或一组单元格中的数字的平均值,例如:=AVERAGE(A1:A10)。3、COUNT函数,用于计算一列或一组单元格中的数字或文本的数量,例如:=COUNT(A1:A10)4、IF函数,用于根据指定的条件进行逻辑判断,并返回相应的结果。

可以。C++ 允许函数嵌套定义和调用。外部函数可定义内置函数,内部函数可在作用域内直接调用。嵌套函数增强了封装性、可复用性和作用域控制。但内部函数无法直接访问外部函数的局部变量,且返回值类型需与外部函数声明一致,内部函数不能自递归。

JavaScript 中,this 的指向类型有:1. 全局对象;2. 函数调用;3. 构造函数调用;4. 事件处理程序;5. 箭头函数(继承外层 this)。此外,可以使用 bind()、call() 和 apply() 方法显式设置 this 的指向。
