4.函数作用域
Javascript开发者面临的一个很大的问题就是函数作用域的问题,因为this在js中是随着函数不同而变化的,并不像java类中指向全局。每个函数内部的this都是不同的。
强烈建议先学习下js的作用域规则(参见《Javascript权威指南》),这里我们将简要介绍作用域是什么?怎么变化?对我们的代码有什么影响?
a.什么是函数作用域Scope
作用域指的是一段正在执行的代码的上下文环境,他决定了什么样的变量对其是可用的。
js有两种类型的作用域:全局作用域和局部作用域。全局作用域下定义的函数和变量在任何地方都是可以访问的。最常见的例子是document和window变量。局部变量和函数是指在一个函数内部定义的,不能被函数外部访问。
作用域链是js解析变量的一种方式,当试图访问一个函数中的变量时,如果这个变量不是在函数内定义的,那么js引擎将遍历作用域链(函数链 原型链)找到与之同名的变量,如果没有则抛出一个错误,这意味着局部的变量会优于全局变量被找到和使用。
下面我们将举几个例子说明作用域是什么工作的
1.第一个例子很简单,我们声明一个全局变量,并通过alert访问它
var myVar = 'Hello from Global Scope!'; alert(myVar); //alerts 'Hello from Global Scope!'
2. 下面这个例子会弹出两个alert,第一个打印Hello from Global Scope!,第二个打印Hello from MyFunction!,说明在函数myFunction中可以访问和修改全局变量
var myVar = 'Hello from Global Scope!'; function myFunction(){ myVar = 'Hello from MyFunction!'; } alert(myVar); //alerts 'Hello from Global Scope!' myFunction(); alert(myVar); //alerts 'Hello from MyFunction!'
3. 我们在myFunction中定义一个局部变量myVar,这样局部变量myVar的作用域是函数myFunction,这样在执行alert(myVar)时将会打印出Hello Global Scope!而不是Hello from MyFunction!,因为这样是相当于在函数内部定义了一个局部变量而不是改变了全局变量的值,且函数外面的alert也不能访问到函数中的myVar变量。而函数中的alert访问的就是函数中定义的myVar了,根据上面说的,他会先访问局部变量。
var myVar = 'Hello Global Scope!'; function myFunction(){ var myVar = 'Hello from MyFunction!'; alert(myVar); } alert(myVar); //alerts 'Hello from Global Scope!' myFunction(); //alerts 'Hello from MyFunction!' alert(myVar); //alerts 'Hello from Global Scope!'
4. 最后我们将演示this关键字的用法,this关键字无处不在,为我们提供了一个访问当前代码执行的上下文环境的引用。下例中使用MyClass的构造器新建一个对象,通过观察log中的this值发现其实新建对象的引用,这意味中我们可以在这个对象上定义属性,并使得他们的作用域只在这个对象内部,不会被对象外部访问到。
function MyClass(){ console.log(this); } var myClass = new MyClass();
5. 如果我们在构造器中添加一个属性,当对象创建后我们可以在构造器中将其alert出来,但是如果我们试图在MyClass作用域外访问this.myProperty,他将不存在,因为这里的this指的是浏览器对象window。
function MyClass(){ console.log(this); this.myProperty = 'Hello'; } var myClass = new MyClass(); alert(myClass.myProperty); // alerts 'Hello' alert(this.myProperty); // alerts 'undefined'