[JavaScript]JS基础知识(中)

作用域和闭包

执行上下文

范围:一段<script>或者一个函数

全局:变量定义、函数声明(一段<script>)

函数:变量定义、函数声明、this、arguments(函数)

在第2行执行之前,a被声明为undefined,而在第5行执行时,函数fn直接被提前完整声明了,所以可以正确执行。

在第6~15行,是函数内的执行上下文,同理,在第8行中读取age的属性,自动为age完成了“var age”的声明,故程序可正常执行。

建议定义要放前面,方便他人阅读。

在函数fn中,bar(100)也会去寻找function bar()的声明,故也能正常输出数字。

关于this、argument,在函数执行之前,this就已经确定了值。

注意“函数声明”和“函数表达式”的区别

注意,执行第1行时,如果是用函数声明的方式定义函数,则可以执行,而使用函数表达式的方式,则报错,因为找不到函数的定义。

this

作为构造函数执行:

作为对象属性执行:

作为普通函数执行:

call apply bind:

call、apply和bind可以修改this的值。其中要注意bind必须要用函数表达式的方式才能执行。

作用域

js中,无块级作用域:

外部可以访问if语句块中的name

有函数和全局作用域:

由于有函数作用域和全局作用域,故两次输出a的值不同。定义到函数里的变量,外部不可调用、改变。

作用域链

关于自由变量:

在fn函数中,并没有定义a,但是fn从其父级作用域中寻找变量。

函数的作用域是由函数定义的时候指定的,而不是函数执行时指定的。

关于作用域链:

F1的父级作用域是全局作用域,f2的父级作用域是f1,因此当打印a时,js向父级作用域中寻找,而f1作用域没有,则再往f1的父级作用域,即全局作用域中寻找,再全局作用域中找到a,而b也同理。

这个寻找的过程是从作用域链中一步步寻找得到的,这就是作用域链。

闭包

函数作为返回值的情况:

F1函数返回了一个函数。将返回的函数赋值给了f1,之后执行f1。

在第5行中,a是自由变量,故到它的父级作用域中寻找,而F1()函数中定义了a = 100,所以a的值为100。

函数作为参数传递的情况:

题目:

1、说一下对变量提升的理解:

变量定义
函数声明(注意和函数表达式的区别)

2、说明this几种不同的使用场景

作为构造函数执行
作为对象属性执行
作为普通函数执行
Call apply bind

3、创建10个<a>标签,点击的时候弹出来对应的序号

错误代码:

执行结果:无论点击哪个链接,都弹出10。原因是在全局作用域中,i在循环结束时的值为10,所以不管之前定义时i的值为多少,总是返回当前作用域的i的值。

正确解法:使用自执行函数(就是不用调用,只要定义完成,立即执行的函数)

正确代码:

结果截图: