函数:是一块JavaScript代码,被定义一次,但可执行和调试用多次。JS中的函数也是对象,所以JS函数可以像其他对象那样操作和传递,所以我们也常常叫函数为函数对象。
function foo(x,y){
if(typeof x === 'number' && typeof y ==='number'){
return x + y;
}else{
return 0;
}
}
foo(1,2);//3
重点
不同的调用方式
直接调用
foo();
对象方法
o.method();
构造器
new foo();
call/apply/bind调用方式
fun.call(o);
创建函数 声明 vs 表达式
函数声明
function add(a,b){
a = +a;
b = +b;
if(isNaN(a) || isNaN(b)){
return;
}
return a + b;
}
函数表达式
//function variable
var add = function(a,b){
//todo
}
(function(){ //立即执行表达式
//todo
})();
return function(){
//todo
};
var add = function foo(a,b){ //命名是函数表达式
//todo
}
函数声明和函数表达式的区别
函数声明前置
//函数声明
var num add(1,2);
console.log(num);//return 3
function add(a,b){
a = +a;
b = +b;
if(isNaN(a) || isNaN(b)){
return;
}
return a + b;
}
//函数表达式
var num add(1,2);
console.log(num);//TypeError:undefined is not a function//不是一个方法
var add = function add(a,b){
a = +a;
b = +b;
if(isNaN(a) || isNaN(b)){
return;
}
return a + b;
}
命名函数表达式(nfe)
var func = function nfe() {};
alert(func === nfe); //ie6-8 false ie9+ error
//递归调用
var func = function nfe(){
//todo
nfe();
}
Function构造器
//a ,b 形参 最后一个形参是函数的方法体
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('var localVal = "local";console.log(localVal);')();//colal localVal仍为局部变量
console.log(typeof localVal);//undefined
var globalVal = 'global';
(functiong(){
var localVal = 'local';
Function('console.log(typeof localVal,typeof global);')(); //local不可访问,全局变量global可以访问
})();//undefined,String;
This
全局this(浏览器)
console.log(this.document === document);//true
console.log(this === window);//true
this.a = 37;
console.log(window.a);37
一般函数的this(浏览器)
function f1(){
return this;
}
f1() === window;//true,global object
function f2(){
"use strict";//see strict mode 严格模式
return this;
}
f2() === undefined;//true
作为对象方法的函数的this
var o = {
prop : 37,
f:function(){
return this.prop;
}
};
console.log(o,f(););//37
var o ={prop:37};
function independent(){
return this.prop;
}
o.f = independent;
console.log(o.f());//logs 37
对象原型链上的this
var o = {f.function(){
return this.a + this.b;
}};
var p = Object.create(o);
p.a = 1;
p.b = 4;
console.log(p.f());
get/set 中的this用法和上面一样,构造器中的this和上面还是一样的
call / apply方法与this
function add(c,b){
return this.a + this.b + c + d;
}
var o = {a:1,b:3};
add.call(o,5,7);//1+3+5+7 =16 //o 给this
add.apply(o,[10,20]);//1+3+10+20 =34 // o 给this
function bar(){
console.log(Object.prototype.toString.call(this)); //拿到this的标签
}
bar.call(7);//Object Number
bind方法与this
function f(){
return this.a;
}
var g = f.bind({a:"test"});//把那个对象的属性设置成this
console.log(g());//test
var o = {a:37,f:f,g:g};
console.log(o.f(),o.g());//37,test
函数属相 和 arguments
function foo(x,y,z){
arguments.length;//2 实参个数,因为foo调用时只传了2个形参,所以实参个数为2
arguments[0];//1
arguments[0] = 10;//绑定x
x;//10
arguments[2] = 100;//参数没有传z,所以arguments无法修改参数z的值,返回仍然是undefined
z;//undefined;
arguments.callee === foo;//true
}
foo(1,2);
foo.length;//3 形参个数为3
foo.name;//"foo" 函数名是foo
注意:在"use strict"严格模式下 arguments无法改变参数的值,并且callee方法无法使用
apply 和 call 方法(浏览器)
function foo(x,y){
console.log(x,y,this);
}
foo.call(100,1,2);//1,2,number[100]
foo.apply(true,[3,4]);//3,4,boolean[true]
foo.apply(null);//undefined,undefined,window //'use strict' 严格模式下返回 undefined ,undefinde,null
foo.apply(undefined);//undefined,undefined,window //'use strict' 严格模式下返回 undefined ,undefinde,undefined
bind方法IE9以上提供的方法
this.x = 9; //全局变量9
var module = {
x:81.
getX:function(){ return this.x};
}
module.getX();//81
var getX = module.getX;
getX() = 9;//指向全局变量this
var boundGetX = getX.bind(module); //重新指向module中的this
boundGetX();//81
bind与currying
function add(a,b,c){
return a + b + c;
}
var func = add.bind(undefined,100); //a绑定100 ,this = undefined
func(1,2);//103 100 + 1 + 2 =103 传了两个参数,所以a = 100
var func2 = add.bind(undefined,200);//a = 100 ,b =200
func2(10);//310 100 + 200 + 10 = 310 //传了一个参数
使用场景
function getConfig(colors,size,otherOptions){
console.log(colors,size,otherOptions);
}
var defaultConfig = getConfig.bind(null,"#CC0000","1024*768");
defaultConfig("123");//"#CC0000","1024*768","123"
defaultConfig("456");"#CC0000","1024*768","456"
bind与new
function foo(){
this.b = 100;
return this.a;
}
var func = foo.bind({a:1});
func();//1
new func();//b:100 new会湖忽略bind的作用
binde方法的模拟 科里化
function foo(){
this.b = 100;
retrun this.a;
}
var func = foo.bind({a:1});
func();//1
new func();//{b:100}
//因为bind是IE9+才能使用的所以,在IE5上使用就需要模拟bind方法
if(!Function.prototype.bind){
Function.prototype.bind = function(oThis){
if(typeof this !== 'function'){
throw new TypeError('what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments,1),
fToBind = this,
fNOP = function(){},
fBound = function();{
return fToBind.apply(this instanceof fNOP ? this:oThis,aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}