一、函数声明和表达式
函数声明: function test() {};
test(); //运行正常
function test() {};
函数表达式: var test = function() {};
test; //undefined
test(); //TypeError
var test = function() {};
命名函数的赋值表达式:
var test = function bar() {
test(); //正常运行
};
test(); //ReferenceError
二、this
1. 全局范围内、函数调用、方法调用、调用构造函数、显示的设置this;
注:在严格模式下,没有全局变量,即this = undefined,在对象的字面量声明语法中,this不能用来指向对象本身;
显示的设置this:
function test(a, b, c) {};
var bar = {};
foo.apply(bar, [1, 2, 3]); //数组将被扩展;
foo.call(bar, 1, 2, 3); //传递到test的参数为: a = 1, b = 2,c = 3;
当使用Function.prototype上的call或apply方法时,函数内的this将被显示设置为函数调用的第一个参数;
2. 常见误解
1. Foo.method = function() {
function test() {
//this 为全局变量;
};
test();
};
Foo.method = function() {
var that = this;
function test() {
//that指向Foo对象;
};
test();
};
三、闭包和引用
闭包:当前作用域总是能访问外部作用域中的变量。
例:
function counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count;
}
};
};
var test = counter(4);
test.increment();
test.get(); //5;
循环中的闭包:
for (var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i); // 10个10;
}, 1000);
};
方法:
1. for (var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e); // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
}, 1000);
})(i);
};
2. for (var i = 0; i < 10; i++) {
setTimeout(function(e) {
return function() {
console.log(e); //0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
}(i), 1000);
};
四、arguments对象
每个函数内都可以访问一个变量arguments,它维护着所有传进来的参数列表,不是一个数组,不能用pop()、push()等数组方法,但是能访问其length;
注:当arguments作为局部变量声明和形参时,arguments对象不会被创建;
注:强烈建议不要使用arguments.callee;
转换为数组:Arrary.prototype.slice.call(arguments);但转化比较慢,不咋推荐;
arguments会创建getter和setter方法,改变形参的值会改变arguments对象的值,反之亦然;
例:
function test(a, b, c) {
arguments[0] = 10;
console.log(a); //10;
b = 20;
console.log(arguments[1]); //20;
var d = c;
d = 9;
console.log(c); //3;
};
test(1, 2, 3);
function test(a) {
'use strict';
a = 10;
console.log(a, arguments[0]); //10, 1
};
test(1);
五、函数间传递参数
1. function foo() {
test.apply(null, argument);
};
function(a, b, c) {};
2. 同时使用call和apply:
function Foo() {};
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
Foo.method = function() {
Foo.call.apply(Foo.prototype.method, arguments);
};
或者:
Foo.method = function() {
var args = Array.prototype.slice.call(arguments);
Foo.prototype.method.apply(args[0], args.slice[1]);
};