执行环境与作用域
执行环境是什么?
所谓的执行环境就是变量和函数所运行的环境, 定义了这些变量或函数访问权, 也决定了它们各自的行为, 每个执行环境都有一个与之关联的变量对象, 而在执行环境中所有变量和函数都保存在这个对象中, 我们无法访问这个对象全局执行环境是什么?
全局执行环境是最外层的执行环境, 一般默认为window对象谁拥有着执行环境?
每个变量对象函数都有自己的执行环境, 当执行一个函数时, 该函数的环境就会被推入一个环境栈中, 当函数执行后, 才会被弹出并且返回执行权作用域链是什么?又有什么作用?
而当函数在一个环境中执行时, 会创建变量对象的一个作用域链( scope chain ), 这个作用域链的主要作用就是用来保证对执行环境有权访问的所有变量和函数的有序访问作用域链的层级?
作用域链的最前线始终都是当前执行环境的变量对象, 如果该环境为函数, 则将其活动对象( activation object )作为第一个变量对象, 该对象便是arguments对象, 而作用域链中的下一个变量对象在来源于包含该环境的外部环境的变量对象, 而以此类推, 将一直延伸到全局执行环境中作用域链中标识符怎么解析?
标识符解析是沿着作用域链一级一级的搜索标识符的过程, 始终从最前端开始再逐级向后回溯, 直到找到该标识符为止, 如果失败, 则导致错误
ES6之前没有块级作用域
也就是说类似与if( ) {}
或者for() {}
之间的变量并不会被销毁而是会被添加到当前执行环境中
ES6 以后可以使用let
定义块级作用域变量
call() 和 apply() 扩充作用域
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>call and apply</title>
</head>
<body>
<p>call和apply都是用于传递参数, 差别在于call需要将参数逐个列出, 而apply更适用于直接传递一个数组</p>
<p>而call()和apply()真正用途是用于扩充函数作用域, 也就是将执行环境添加到参数中</p>
</body>
<script>
window.color = "red";
var o = { color: "blue" };
function sayColor() {
console.log(this.color);
}
sayColor(); // red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
/*
在这里, call将执行环境扩充到了o对象中, 所以输出时以o对象作为执行环境, 所以输出时将为blue
*/
</script>
</html>
Global对象
该对象是ECMAScript中最后的对象, 所有不属于任何其他对象的属性和方法, 最终都是它的属性和方法, 即所有全局作用域中定义的属性和方法都是Global对象的属性
eval() 方法
该方法是ECMAScript中最强大的一个方法, 它只接受一个参数, 也就是需要执行的ECMAScript字符串, 它本身就类似于一个ECMAScript解析器
eval("alert('hi')")
通过 eval()
执行的代码将会被视作为包含该次调用的执行环境的一部分, 也就是说被执行的代码具有与该执行环境相同的作用域链, 意味着通过eval()
执行的代码可以引用在包含环境中定义的变量
var msg = 'hello world';
eval("alert(msg)") //hello world;
/*在严格模式中外部访问不到eval()创建的任何变量或函数*/
一些关于JavaScript中引用类型的纪录
- 引用类型与传统面向对象程序设计中的类相似, 不过实现不同
- Object是一个基础类型, 其他所有类型都从Object中继承了基本的行为
- Array类型是一组值的有序列表, 同时还提供了操作和转换这些值的功能
- Date类型提供了大量关于日期和时间的信息和计算功能
- RegExp类型是ECMAScript支持正则表达式的一个接口
- Function类型创建了函数
- 三种基本包装类型分别是 Boolean, Number和String
- 作用域最早的内置对象, Global和Math, 不过是不能直接访问Global对象的, 但是Web浏览器本身实现了承担该角色的window对象