函数
1. 函数声明
function funcName(){
...
}
由于声明提前,可以在定义之前调用此函数。不能出现在循环,条件判断,或者try/catch/finally以及with语句里。
此外,要注意函数内的的变量声明也是会提前的。这里经常笔面试出题。
var scope="global";
function scopeTest(){
console.log(scope);
var scope="local"; //scope变量提前到console.log语句前。
}
scopeTest(); //undefined
2. 函数表达式(函数名可选,在递归时通常会写函数名)
var f = function(){
...
}
不能在定义之前调用。
函数调用及其调用上下文
1. 作为函数
非严格模式下,调用上下文(this值)是全局对象,严格模式下,调用上下文是undefined.
2. 作为方法
调用上下文和与函数调用不同。指的是当前对象,而不是全局对象。
var o = { // An object o.
m: function() { // Method m of the object.
var self = this; // Save the this value in a variable.
console.log(this === o); // 1.Prints "true": this is the object o.
f(); // 作为函数调用,因此其调用上下文是全局对象或者undefined。所以2的结果为false
function f(){ // A nested function f
console.log(this === o); // 2."false": this is global or undefined
console.log(self === o);// 3."true": self is the outer this value.
}
}
};
o.m();// 作为方法调用,其调用上下文为当前对象。因此1的结果为true。
当方法的返回值是对象时,对象还可调用其方法,行成方法链。就像jQuery一样。
var ob = {
m: function(a) {
console.log(a);
return this;
},
}
ob.m(5).m(6);
3. 作为构造函数
函数/方法前带有关键字new,就构成了构造函数调用。
构造函数调用创建一个新的空的对象,这个对象继承自构造函数的prototype属性。构造函数的调用上下文为新创建的对象。
构造函数通常不用return关键字,通常返回的是新创建的的对象的值。比如熟悉的var obj = new Object;
。
当构造函数显式地使用return语句返回对象时,返回的就是该对象;如果返回的是原始值,则跟没有显式使用return是一样的。
function test1(a,b,c){
this.a = a;
this.b = b;
return c; //returns a primitive value
}
//Results
> var x = new test1(4,5,6);
undefined
> x
{ a: 4, b: 5 }
function test2(a,b){
this.a = a;
this.b = b;
return {1:2}; //returns an object
}
//Results
> var y = new test2(7,8);
undefined
> y
{ '1': 2 }
4. 通过call(),apply()间接调用
第一个实参是要调用函数的母对象,它是调用上下文,f.call(o)
以及f.apply(o)
的意思是:以对象o的方法来调用f函数。
严格模式下,第一个实参都会变成this的值,哪怕传入的实参是原始值/null/undefined
非严格模式下,传入的null/undefined会被全局变量代替。
apply和call的区别在于传入实参的形式不同,比如apply(o,[x,y,z...])
与call(o,x,y,z,...)
。