重点。
1、函数介绍
函数是一块JavaScript代码,被定义一次,但可执行和调用多次。JS中的函数也是对象,所以JS函数可以像其他对象那样操作和传递,所以我们也常叫JS中的函数为函数对象。
注意:
返回Return
return语句可以使函数提前返回。
一个函数总会返回一个值,函数的返回值,依赖于return语句。
一般的函数调用:如果没有return语句的话,默认会在所有代码执行完以后返回undefined。
如果是作为构造器,外部使用new去调用的话,如果没有return语句,或者return的是基本类型的话,默认会将this作为返回。
反之,如果return的是对象,将这个对象作为new构造器的返回值。
2、函数的属性和方法【20170501】
函数属性
- length属性
- prototype属性
- 自定义属性
函数方法
- call()
- apply()
3、函数的相关内容
函数内容较多,重点有:
- this
- arguments
- 作用域
- 不同调用方式
- 直接调用foo()
- 对象方法o.method()
- 构造器new Foo()
- call/apply/bind调用 func.call(o)
- 不同创建方法
二、函数声明和表达式
1、函数声明
function add(a,b){ a=+a; b=+b; if(isNaN(a)||isNaN(b)){ return; } return a+b; }
一个完整的语句以function开头,也不加括号,也不加叹号,也不会把它括起来,也不会把它作为赋值语句的右值等待。这样定义的函数就叫函数声明。
2、函数表达式
1、 函数变量
函数表达式赋值给变量。
//函数变量 function variable var add=function(a,b){ //do sth }
2、立即执行函数表达式(IEF)
把一个匿名函数用括号括起来,再去直接调用。
//立即执行函数表达式 IEF(Immediately Executed Function) (function(){ })();
3、作为返回值的函数表达式
将函数对象作为返回值,函数也是对象。
//first-class function return function(){ //do sth }
4、命名式函数表达式(不常用)
同样是赋值给一个变量,但这个函数不是匿名函数,而是有一个名字的函数,
//NFE (Named Function Expression) var add=function(a,b){ //do sth }
3、函数声明和函数表达式的区别
最主要的区别是函数声明会被前置。
函数声明,在声明前调用也可以,因为会前置。
函数表达式在声明前调用会报错:undefined is not a function。
函数表达式中
var add=function(a,b){//do sth};
变量的声明会被提前,var add会提前,add被提前后它的值是undefined。
当把一个undefined的变量尝试像函数那样去调用的时候,就会报异常:undefined is not a function。
注意:在《jquery按钮绑定特殊事件》
中第一次点击按钮触发一个事件,第二次点击触发另一个事件。遇到类似的情况,
//不要这样做 if(condition){ function sayHi(){ alert("Hi!"); } }else{ function sayHi(){ alert("Yo!"); } } //可以这样做 var sayHi; if(condition){ sayHi=function(){ alert("Hi!"); } }else{ sayHi=function(){ alert("Yo!"); } }
命名函数表达式(NFE)
函数名字可以被调试器和开发工具识别。
经典bug
命名函数表达式里的名字nfe在 函数对象创建所在的作用域中 正常情况下是访问不到的。所以会报错:nfe is not defined
老的IE浏览器(IE6~8)仍然可以访问得到,但是nfe和func又不是同一个对象。
命名函数表达式相关规范:
规范规定:命名函数表达式名字(标识符)在函数体的作用域内有效,且不能被覆盖。
b = function c() { a = 1, b = 2, c = 3; console.log(typeof c); // function };
命名函数表达式应用:
调试
递归调用自己
//递归调用 var func=function nfe(){/** do sth. **/ nfe();}
5、函数构造器
除了函数声明和函数表达式,还有一种不常见的构造函数的方式—使用函数构造器。
Function()中参数可以有多个,前面的参数表示函数对象里面的形参,最后一个参数表示函数体里面的代码。
函数体里的代码也是字符串,这也是为什么函数构造器不常用的原因。
var func=new Function('a','b','console.log(a+b);'); //创建一个对象,有a,b2个形参,函数体里面是输出a+b func(1,2);//3 //不管用new还是不用new最后得到的结果都是一样的。 var func=Function('a','b','console.log(a+b);'); func(1,2);//3
Function构造器作用域和其他处理与一般函数声明和函数表达式的差异
1、在Function构造器里面创建的变量仍然是局部变量,
//CASE1 Function('var localVal="local";console.log(localVal);')();//立即执行 console.log(typeof localVal); //undefined
2、Function函数声明能访问到全局变量,却访问不到它的外函数中定义的变量。
local不可访问,全局global可以访问。
三、this
1、全局的this(浏览器)
全局作用域下的this一般指向全局对象,浏览器汇总的全局对象就是window。
2、一般函数的this(浏览器)【重点】
全局作用域下直接调用f1(),this就仍然指向全局对象,浏览器中就是window,在node.js里面就是global对象。
严格模式下直接调用f2(),this执行是undefined。
注意:语言设计上的不足【update 20170306】
调用函数时,this被绑定到全局对象。如下内部函数调用时this也是绑定到全局对象window。
function outer(){ console.log(this===window); function inner(){ console.log("内部函数:"+(this===window)); } inner(); }