JavaScript 函数
函数是 JavaScript 中的基本组件之一。一个函数是 JavaScript 过程 — 一组执行任务或计算值的语句。要使用一个函数,你必须将其定义在你希望调用它的作用域内。
一个 JavaScript 函数用function关键字定义,后面跟着函数名和圆括号。
函数声明
一个函数定义(也称为函数声明,或函数语句)由一系列的function关键字组成,依次为:
- 函数的名称。
- 函数参数列表,包围在括号中并由逗号分隔。
- 定义函数的 JavaScript 语句,用大括号{}括起来。
例如,以下的代码定义了一个简单的square函数:
函数square使用了一个参数,叫作number。这个函数只有一个语句,它说明该函数将函数的参数(即number)自乘后返回。函数的return (en-US)语句确定了函数的返回值:function square(number) { return number * number; }
原始参数(比如一个具体的数字)被作为值传递给函数;值被传递给函数,如果被调用函数改变了这个参数的值,这样的改变不会影响到全局或调用函数。return number * number;
如果你传递一个对象(即一个非原始值,例如Array或用户自定义的对象)作为参数,而函数改变了这个对象的属性,这样的改变对函数外部是可见的,如下面的例子所示:
function myFunc(theObject) {
theObject.make = "Toyota";
}
var mycar = {make: "Honda", model: "Accord", year: 1998};
var x, y;
x = mycar.make; // x 获取的值为 "Honda"
myFunc(mycar);
y = mycar.make; // y 获取的值为 "Toyota"
// (make 属性被函数改变了)
词法作用域
编译型语言,编译步骤分为:词法分析、语法分析、语义检查、代码优化和字节生成。
而解释型语言,通过词法分析和语法分析得到语法分析树后,就可以开始解释执行了。
js执行过程:
- 读入第一个代码段(js执行引擎并非一行一行地执行程序,而是一段一段地分析执行的)
- 做词法分析和语法分析,有错则报语法错误(比如括号不匹配等),报错后不再向后执行
- 对【var】变量和【function】定义做“预解析“(永远不会报错的,因为只解析正确的声明)
- 执行代码段,有错则报错(比如变量未定义)
- 如果还有下一个代码段,则读入下一个代码段,重复步骤2
- 结束
上面的过程,我们主要是分成两个阶段
javascript解析:就是通过语法分析和预解析构造合法的语法分析树。
javascript执行:执行具体的某个function,JS引擎在执行每个函数实例时,都会创建一个执行环境(ExecutionContext)和活动对象(activeObject)(它们属于宿主对象,与函数实例的生命周期保持一致)
测试:
var a = 10;
function fn1(){
var a = 20;
foo()
};
function foo(){
console.log(a)
}
fn1()
//10 foo作用域在window
执行上下文
每调用一个函数,就会创建一个新的执行上下文。
上下文建立过程:
- 声明变量,函数,确定arguments对象,参数
- 做词法分析形成语法分析树,建立作用域链
- 确定this的值
- 变量赋值,函数引用,执行其它代码
var a = 10;
var b = {
a:20,
fn(){
foo();
},
fn1(){
console.log(this.a)
}
}
function foo(){
console.log( this.a )
}
b.fn()
第一步:
var a,b,foo;
第二步:
第三步:
全局环境内this为window
b.fn 和 b.fn1内this为b
foo内this为window
第四步:
a = 10;
b = {
a:20,
fn(){
foo();
},
fn1(){
console.log(this.a)
}
}
function foo(){
console.log( this.a )
}
b.fn1() // 20
b.fn() // 10 foo this指向window,所以引用的a是全局变量