@GivenCui
2016-05-25T19:13:30.000000Z
字数 3356
阅读 810
js高级
作用域 : 变量和函数的访问范围, 作用域可以控制变量和函数的可见性和生命周期.
- 全局作用域
- 局部作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>全局作用域与局部作用域</title>
<script type = "text/javascript">
/*
全局作用域
*/
// 全局变量在全局作用域中,也就是说,在任何位置都可以访问到这个全局变量
var globalName = "这是全局变量" ;
// 在全局作用域中访问
console.log("全局作用局访问: " + globalName);
// 在普通的函数中访问
function fn () {
console.log("在普通的函数中访问: "+ globalName);
}
fn();
// 在构造函数中访问
function Person () {
this.name = globalName;
}
var person = new Person();
console.log("在构造函数中访问: " + person.name);
// 在字面量对象中访问
var obj = {
name : globalName
}
console.log("在字面量对象中访问: " + obj.name);
/*
* 局部作用域
*/
function fn2() {
var partName = "这是局部变量";
// 局部变量在当前作用域下一定可以访问到
console.log(partName);
function subFn() {
console.log("某个函数的子函数(内部函数),也可以访问到当前函数的局部变量" + partName);
}
subFn();
}
fn2();
// try catch语句: 用来捕捉异常,如果报错程序会停止运行,但是用try catch捕捉的话就算出现异常,程序照样会执行.
// 使用场景 : 有报错风险的地方使用
try{
// 有报错风险的代码
console.log(partName); // 报错
} catch (exception) { // catch中的参数叫什么都行
// 捕捉异常后,打印异常信息
console.log(exception.toString());
}
console.log("程序能正常运行");
</script>
</head>
<body>
</body>
</html>
- 1.在JS中没有块级的概念. 其它语言中“{}”中的都是局部变量,但在JS中,只有函数的作用域内的才是局部变量,例如 for(){} if(){}else{}等中的“ {} ”在JS中不是块级.
- 2.在JS中, 如果没有用var去声明变量的话, 那么这个变量就是全局变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作用域的注意事项</title>
<script type = "text/javascript">
// 1、在JS中是没有块级概念的
function fn () {
for (var i = 0; i < 4 ; i++) {
}
// 在JS中可以访问到
console.log(i);
}
fn();
// 2. 不用var的变量是全局变量
function fn2 () {
name = "abc";
}
fn2();
// 可以访问到不用var声明的变量
console.log(name);
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>混合练习</title>
<script type = "text/javascript">
var a = "a"; // 全局变量
function fn3 (d) {
b = "b"; // 全局变量 (没var)
var c = "c"; // fn3的局部变量
function subFn() {
var e = d; // subFn()的局部变量
if (true) {
var f = "f"; // subFn()的局部变量
}
}
subFn();
}
fn3();
</script>
</head>
<body>
</body>
</html>
作用域链 : 访问某个变量,先去当前的作用域去查找这个变量,如果查找不到,就沿着作用域链(该作用域的父级作用域去找), 以此类推,直到找到头为止,最顶端是window对象,全局作用域. 如果找不到,就会报错.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>作用域链</title>
<script type = "text/javascript">
// 作用域链
var name = "abc";
function fn () {
var name = "abc";
function subFn1 () {
var name = "bcd";
console.log("name"); // bcd
}
function subFn2 () {
console.log(name); // abc
}
/*
原理是:
1. 预解析
2. 逐条指行
*/
// subFn1() --> fn --> window(作用域链的最顶端)
subFn1();
subFn2();
}
fn()
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>for循环中套函数陷阱</title>
<script type = "text/javascript">
// 经典面试题
function initBtnEvent () {
for (var i =1; i < 4; i++) {
var tempBtn = document.getElementById("button" + i);
tempBtn.addEventListener("click", function () {
alert("button " + i);
});
}
}
window.onload = initBtnEvent;
</script>
</head>
<body>
<input type = "button" value = "Button1" id ="button1" />
<input type = "button" value = "Button2" id ="button2" />
<input type = "button" value = "Button3" id ="button3" />
</body>
</html>
JS中this关键字的指向是动态的,动态有好处也有坏处,有的时候会出现一些意想不到的结果,那么我们可以通过call和apply等方法对this关键字进行固定。
1、call方法:可以指定函数内部的this指向,并且进行该函数。
2、apply :和call方法功能一样,只不过参数为数组。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>固定this的方法</title>
<script type = "text/javascript">
// 1. call方法
var name = "abc,this访问的是全局";
var obj = {
name : "bcd,通过call让this指向了obj"
};
function fn () {
console.log(this.name);
}
fn();
// 通过函数调用call方法, 可以改变this的指向, 并且在参数所在的环境中运行.
fn.call(obj);
// 待参数的
function fn2 (a, b) {
console.log(a + b);
}
// 在全局环境中运行
fn2.call(this,5,8); // 13
// apply方法和call功能一样, 就是参数换成了数组
fn2.apply(this, [6, 9]); // 15
</script>
</head>
<body>
</body>
</html>