JavaScript函数基础
2015-10-24 18:11
477 查看
函数只定义一次,但是可以被执行或调用任意次,在js中函数就是对象,所以也可以为函数添加属性和方法。js的函数可以嵌套在其他函数中调用,这就是闭包。
函数定义的俩种方式:函数声明,函数表达式。
首先看一个概念,执行上下文,活动的上下文构成一个堆栈,堆栈的底部就是全局上下文,顶部就是当前活动的上下文。进入上下文就会获得程序的控制权,在执行完毕后,就会在堆栈上移除。在执行上文时会有3件事情,1是初始化参数,2是函数声明,3是变量声明。所以函数函数声明可以提前调用也不会报错,然而函数表达式就不可以这样。
注意函数return后就结束函数代码的执行,也就是该函数执行完毕,在堆栈中被移除了,假如一个函数没有return值得话,默认返回undefined
函数调用 有4种方式: 作为函数,作为方法,作为构造函数,使用call或者apply间接调用。
函数的参数可以传入的是参数表达式,参数表达式在计算完毕后会返回一个值,值将会作为实参传递给声明函数时所定义的形参。
作为方法调用时要注意,实际上作为方法调用时实际上都会传入一个隐式的实参,这个实参也就是一个对象,这个对象也就是这个拥有这个方法的对象。
构造函数调用,构造函数并没有返回值,其调过程是,首先会创建一个空对象,这个空对象的
函数的形参和实参,当函数实参的个数少于形参时,剩下的形参会被赋值为undefined,如果实参个数大于形参的话,超过形参个数的实参会被忽略。
注意可以在可选参数前加上
函数也是对象,函数也可以定义属性,函数也可以定义属性,在需要创建全局变量来解决问题的时候,其实可以尝试一下用为函数添加属性来解决问题,因为这样可以避免一些由全局变量产生的一系列问题。
函数闭包,函数闭包在js中非常常见,简单的我们可以理解为在一个函数a内创建的函数b,我们把函数b叫做闭包,闭包在js中的概念非常重要。
上面的函数俩个函数在同一个父作用域下创建,值调用了一次父函数,所以产生的俩个字函数共用一个[[scope]]属性,而下面的这个f1函数与f2函数显然不是共用的同一个[[scope]]属性,翻看权威指南我们可以得到,每次调用函数都会创建一个新的作用域链,这就可以解释我们产生的这俩种区别了,第一次共用一个[[scope]]属性的原因就是,父函数只调用了一次,子函数的scope属性,保存着父函数的scope属性的引用,所以俩个函数的[[scope]]指向内存中的同一个地址;而下面的代码,函数f1在创建时调用了一次函数create,create函数开辟内存,创建了一个scope属性,函数foo(也就是f1)的[[scope]]属性保存着这次调用create函数所创建的create函数的scope属性的地址。同理f2的[[scope]]属性保存着的是第二次调用create函数所创建的create函数的scope属性的地址。
函数定义的俩种方式:函数声明,函数表达式。
首先看一个概念,执行上下文,活动的上下文构成一个堆栈,堆栈的底部就是全局上下文,顶部就是当前活动的上下文。进入上下文就会获得程序的控制权,在执行完毕后,就会在堆栈上移除。在执行上文时会有3件事情,1是初始化参数,2是函数声明,3是变量声明。所以函数函数声明可以提前调用也不会报错,然而函数表达式就不可以这样。
foo(); // 可以 fun(); // 报错 function foo () { console.log(1); } var fun = function () { console.log(2); }
注意函数return后就结束函数代码的执行,也就是该函数执行完毕,在堆栈中被移除了,假如一个函数没有return值得话,默认返回undefined
函数调用 有4种方式: 作为函数,作为方法,作为构造函数,使用call或者apply间接调用。
函数的参数可以传入的是参数表达式,参数表达式在计算完毕后会返回一个值,值将会作为实参传递给声明函数时所定义的形参。
作为方法调用时要注意,实际上作为方法调用时实际上都会传入一个隐式的实参,这个实参也就是一个对象,这个对象也就是这个拥有这个方法的对象。
构造函数调用,构造函数并没有返回值,其调过程是,首先会创建一个空对象,这个空对象的
__proto__(原型)也就是该构造函数的
prototype对象,构造函数内的this会指向这个空对象,最后构造函数会返回这个空对象。
函数的形参和实参,当函数实参的个数少于形参时,剩下的形参会被赋值为undefined,如果实参个数大于形参的话,超过形参个数的实参会被忽略。
注意可以在可选参数前加上
/*optional*/来标记这是一个可选参数
function foo (a, /* optional */b) { b = b ? b : 0; return a + b; }
arguments对象是由函数形参组成的一个类数组对象,这里面的坑比较多,
arguments对象的callee属性代表的是该函数,但是在严格模式下是禁用的,函数名.caller返回的是当前函数执行的环境。
函数也是对象,函数也可以定义属性,函数也可以定义属性,在需要创建全局变量来解决问题的时候,其实可以尝试一下用为函数添加属性来解决问题,因为这样可以避免一些由全局变量产生的一系列问题。
函数闭包,函数闭包在js中非常常见,简单的我们可以理解为在一个函数a内创建的函数b,我们把函数b叫做闭包,闭包在js中的概念非常重要。
var fun1,fun2; function foo () { var x = 10; fun1 = function () { console.log(++x); }; fun2 = function () { console.log(--x); } } foo(); fun1(); // 11 fun2(); // 10 // 对比下面这个函数 function create() { var x = 10; function foo () { console.log(++x); } return foo; } var f1 = create(); var f2 = create(); f1(); // 11 f2(); // 11
上面的函数俩个函数在同一个父作用域下创建,值调用了一次父函数,所以产生的俩个字函数共用一个[[scope]]属性,而下面的这个f1函数与f2函数显然不是共用的同一个[[scope]]属性,翻看权威指南我们可以得到,每次调用函数都会创建一个新的作用域链,这就可以解释我们产生的这俩种区别了,第一次共用一个[[scope]]属性的原因就是,父函数只调用了一次,子函数的scope属性,保存着父函数的scope属性的引用,所以俩个函数的[[scope]]指向内存中的同一个地址;而下面的代码,函数f1在创建时调用了一次函数create,create函数开辟内存,创建了一个scope属性,函数foo(也就是f1)的[[scope]]属性保存着这次调用create函数所创建的create函数的scope属性的地址。同理f2的[[scope]]属性保存着的是第二次调用create函数所创建的create函数的scope属性的地址。
相关文章推荐
- 详解JavaScript编程中的数组结构
- js写一个日期Ⅱ(完结)
- BZOJ1028[JSOI2007]麻将
- Atititjs javascript异常处理机制java异常转换.js exception process
- javascript面向对象实现java常用的1StringBuffer,Map,Collection,List,Set
- JS Date
- Web性能优化:延迟加载JS
- 向JavaScript的数组中添加元素的方法小结
- chart.js图表库案例赏析,饼图添加文字
- Ext Store 转为对象数组字符串
- javascript 数组转二维数组
- JavaScript之 ------ 综合应用
- JavaScript异步加载浅析
- JavaScript中数组的合并以及排序实现示例
- jsp中购物车的实现思路
- 使用javaScript动态加载Js文件和Css文件
- 何为js的语句声明
- a href=#与 a href=javascript:void(0) 的区别
- js判断日期时间有效性的方法
- js判断ie 火狐 还是chrome浏览器