1.定义函数的两种方法:
1.函数声明
function functionName(arg0,arg1){
}
特点:函数预解析,代码执行的时候,可以先调用后执行,因为预解析;
a()
function a() {
console.log("s")
};
2.函数表达式
var functionName=function(arg0,arg1){
}
特点:创建的函数是匿名函数,函数名子是空字符串;与定义变量一样,
a()
var a=function (){
console.log("123");
} // Uncaught TypeError: a is not a function at
不要在if代码体中定义函数
2. 递归
function factorial(num){ if(num<=1){ return 1; }else{ return num*factorial(num-1) //也可以换成 return num*argument.callee(num-1);
} }
这里argument.callee(num-1)指的是正在执行的函数,使用argument.callee代替函数名,可以确保无论怎么样调用的函数都不会出问题,因此,在编写递归函数时,使用argument.callee比函数名可靠;
严格模式:
var fac=(function f(num){
if (num<=1){
return
}else{
return num* f(num-1)
}
)
严格模式,不能通过脚本访问argument.callee,访问这个属性会导致错误,不过,可以使用命名函数表达式来、
3.闭包
有权访问另一个作用域中变量的函数
1.闭包与变量
function createFunction(){ var result=new Array(); for(var i=0;i<10;i++){ result[i]=function(){ return i; } } return result; }
var a=createFunction()[0]();
console.log(a); //10,预想的是0;为什么是10,定义函数其实只是定义了一个,地址,其内容只是字符串,真正调用的时候,i没有在当前作用于找到变量,就会去他的父作用域寻找,等找的时候for()循环已经结束,i=10;所以全都是10;
解决办法:自执行函数
function createFunction(){
var result=new Array();
for(var i=0;i<10;i++){
result[i]=(function(){
return i;
})();
}
return result;
}
var a=createFunction();
console.log(a); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 每一次赋值的函数都执行一次;
4.this
1.全局函数中,this等于window,
var x=2; function test(){ var x=1; alert(this.x) } test() //2
2.作为对象调用时,指向上一级对象
var x=2; function test(){ var x=1; alert(this.x) } var o={x:100,f:test}; o.f() //100
3.构造函数,指向实例
var x=2; function Test(){ var obj=new Object; obj.name="xiaomi"; obj.f=function() { alert(this.name); } return obj; } var t=new Test; t.f() //“xiaomi”
4.appli/call/bind 顶包,指向赋予的新作用域
var x=0; function test() { alert(this.x) } var obj={x:100} test.call(obj); //100 call()空值,则指向全局window
5.内存泄漏
function test(){ var element=document.getElementById("box"); element.onclick=function () { alert(element.id); } } test() //以上代码创建了一个作为element元素事件处理程序的闭包,而闭包又创建了循环引用,只要点击调用,就会应用element元素,因此他的内存占用永远无法被收回;
改版后
function test(){ var element=document.getElementById("box"); var id=element.id; //需要的数据保存在变量中 element.onclick=function () { alert(id); //每次调用变量 } element=null; //变量设置为空,告诉浏览器没事给他收回去 } test()
6.模仿块级作用域
js没有块级作用域概念
function test(){ for(var i=0;i<6;i++){ alert(i)//0,1,2,3,4,5 } alert(i); //6 如果for是一个块,下面的alert()就访问不到i; } test()
js 变量赋值的懒惰
function test(){ for(var i=0;i<6;i++){ alert(i) } var i; alert(i); //犹豫他很懒,知道有i变量,没不会重复声明,如果赋值了就不一样了; } test()
(function(){ //我是块级作用域 })()
var someFunction=function(){
//我也是块级作用域
}
7.私有变量
严格讲,js没有私有成员的概念,所有对象属性都是公有的。不过,倒是有一个私有变量的概念,任何函数中的定义的变量,都可以认为是私有变量,因此不能在函数的外部访问这些变量。
8.单例模式
var singleton={ name:value, method:function () { // 这里是方法 } }
模式通过为单例添加私有变量和特权方法能够使其得到增强,其语法形式如下: