函數的調用 直接調用 foo(); 對象方法 o.method(); 構造器 new Function(); call/apply/bind func.call(o); 函數聲明和表達式 函數聲明會被前置,函數表達式變數聲明會被前置,但是值為 。 函數聲明 函數表達式 將函數賦值給一個變數 匿名函數 ...
函數的調用
- 直接調用 foo();
- 對象方法 o.method();
- 構造器 new Function();
- call/apply/bind func.call(o);
函數聲明和表達式
函數聲明會被前置,函數表達式變數聲明會被前置,但是值為undefined
。
函數聲明
function func(a, b) {
//do sth
}
函數表達式
將函數賦值給一個變數
var func = function(a, b) { //do sth };
匿名函數(IEF 立即執行函數表達式)
(function() { //do sth })();
返回函數對象
return function() { //do sth };
命名函數表達式(NEF)
var add = function foo(a, b) { //do sth };
命名函數表達式存在一些經典的bug,例如在執行如下代碼時:
var func = function nfe() {};
alert(func == nfe);
IE6會提示為false
,IE9+中nfe外部並不可見,提示為nfe is undefined
。
命名函數表達式主要可以應用在調試和遞歸調用時。
var func = funtion nfe(){/* do sth */ nfe();};
但也可直接通過func
變數名來執行遞歸調用,因此命名函數表達式並不常用。
function構造器
var func = new Function('a', 'b', 'console.log(a + b);');
func(1, 2); //3
var func = Function('a', 'b', 'console.log(a + b);');
func(1, 2) //3
function構造器的作用域
Function('var localVal = "local"; console.log(localVal);')();
console.log(typeof localVal);
// result: local, undefined
// localVal仍未局部變數
var globalVal = 'global';
(function() {
var localVal = 'local';
Function('console.log(typeof localVal, typeof globalVal);')();
})();
//result: undefined, string
//local不可訪問,全局變數global可以訪問
各方式對比
函數聲明 | 函數表達式 | 函數構造器 | |
---|---|---|---|
前置 | 是 | ||
允許匿名 | 是 | 是 | |
可立即調用 | 是 | 是 | |
在定義該函數的作用域通過函數名訪問 | 是 | ||
沒有函數名 | 是 |
this
全局的this
全局的this一般即是瀏覽器
console.log(this.document === document); //true
consloe.loh(this == window); //true
this.a = 37
console.log(window.a); //37
一般函數的this
一般函數的this仍然指向全局對象,瀏覽器中即為window
fucntion f1(){
return this;
}
f1() === window; //true, global, object
嚴格模式下,this指向undefined
fucntion f2(){
"use strict";
return this;
}
f2() === undefined; //true
作為對象方法的函數this
對象方法中的函數this會指向具體的對象
var o = {
prop: 37;
f: function() {
return this.prop;
}
};
console.log(o.f()); //logs 37
也可以通過外部定義函數
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent
console.log(o.f()); //logs 37
通過call
和apply
調用指定this
function add(c, d) {
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); //1 + 3 + 10 + 20 = 34
function bar() {
console.log(Object.prototype.toString.call(this));
}
bar.call(7); //"[object Number]"
一般模式和嚴格模式下使用apply
的區別
function foo(x, y) {
console.log(x, y, this);
}
foo.apply(null); // undefined, undefined, window
foo.apply(undefined); // undefined, undefined, window
// 嚴格模式下
foo.apply(null); // undefined, undefined, null
foo.apply(undefined); // undefined, undefined, undefined
'bind'方法與this
通過ES5提供的bind方法,可以將函數的this綁定到一個對象上,bind之後this不可變。
function f(){
return this.a
}
var g = f.bind({a: "test"}):
console.log(g()); //test
var o = {a: 37, f:f, g:g};
// g()中的this不會再改變
console.log(o.f(), o.g()); //37, test
函數屬性和對象
function foo(x, y, z) {
arguments.length; //2
arguments[0]; //1
arguments[0] = 10;
x; // change to 10; 嚴格模式下仍然是1
arguments[2] = 100;
z; // still undefined !!!
arguments.callee === foo; // true 嚴格模式下不能使用
}
foo(1, 2)
foo.length; // 3
foo.name; // "foo"
使用bind()
方法currying函數
function add(a, b, c) {
return a + b + c;
}
var func = add.bind(undefined, 100);
func(1, 2); // 100綁定到a上,result:103
var func2 = func.bind(undefoned, 200);
func2(10); // 200綁定到b上,result:310
bind和new的使用
function foo() {
this.b =100;
return this.a;
}
var func = foo.bind({a:1});
func(); // 1
// 使用new時,除非指定返回一個對象,否則會返回this,
// 同時this會被初始化為一個空對象的prototype
new func(); //{b: 100}