JS函数深入
函数的本质是对象
三种定义方式
1、 字面量=function声明
function add() { // body... } add();
2、 var赋值表达式
var add = function (argument) { // body... }; add(); var add = function fn(argument) { // body... fn(); add(); }; add(); fn();//会报错,只能在函数体内调用
3、 构造函数
var add = new function('num1', 'num2', 'return num1 + num2;'); add();
三种定义方式区别:
字面量=function声明:预加载时add=function
console.log(add()); function add() { return 1; }
var赋值表达式:预加载时add=undefined
console.log(add()); var add = function () { return 1; };
构造函数:少用
杂七杂八的知识点:
js中没有块级作用域,所以不会在if中发生预解析,在外部预解析的时候,if中声明的所有函数都会被提前,所以无法达到按需定义的目的。
内部函数可以访问外部函数的变量(作用域链的机制)
案例:写出一个加法(add)函数,并在其内部定义一个函数(isnumber),用来判断add的参数是否可以转化为数字类型进行相加,
如果可以,就在页面中输出结果;
如果不能就退出add,给出提示“请传入数字类型的参数”
function add(num1,num2){ if(isnan(num1) || isnan(num2)){ alert('请传入数字类型的参数'); return; }else{ return parseint(num1)+parseint(num2); } }
var num1=prompt('请输入数字1');
var num2=prompt('请输入数字2');
alert(add(num1,num2));
案例:匿名函数也是函数,当它自执行的时候会创建函数作用域,它里面的变量和函数都是局部的,当匿名函数执行完毕后会被销毁。所以我们在外面访问不到add
function () { function add(num1,num2){ return num1+num2; } }(); document.write(add(1,2));//报错
匿名函数自执行方式:
var add = function () { console.log(1); }(); (function () { console.log(1); })(); !+-~function () { console.log(1); }();
递归调用:递归调用就是自己调用自己,但切记一定要有终止条件,否则函数将无限递归下去
function factorial(num) { if (num <= 1) return 1; return num * factorial(num - 1); // return 5 * 4! = 5 * 4 * 3! =... 5 * 4 * 1! } console.log(factorial(5));
方法的调用:
document.onclick = function () { console.log('你点击了文档!'); }; document.onclick();
var operation = { add: function (num1, num2) { return num1 + num2; }, subtract: function (num1, num2) { return num1 - num2; }, '@': function () { console.log('@'); }, key: function () { // body... } }; console.log(operation.add(1, 2)); console.log(operation['@'](1, 2)); //@符比较特别 var key = 'add'; console.log(operation[key](1, 2));
链式调用
var operation = { add: function (num1, num2) { console.log(num1 + num2); return this; }, subtract: function (num1, num2) { console.log(num1 - num2); return this; }, '@': function () { console.log('@'); }, key: function () { // body... } }; operation.add(1, 2).subtract(2, 1);
间接调用:
对象没有call和apply方法,只有函数有
call和apply的唯一区别就在它们传参的方式上
apply可以将数组和类数组一次性的传递进函数中,call只能一个一个的传;
var name = 'xm'; var person = {}; person.name = 'xh'; person.getname = function () { return this.name; }; console.log(person.getname()); //this指向person console.log(person.getname.call(window)); //this指向window console.log(person.getname.apply(window)); //this指向window function add(num1, num2) { return num1 + num2; } console.log(add(1, 2)); var datas = [1, 2]; console.log(add.call(window, 1, 2)); console.log(add.apply(window, datas)); //apply(ele,[])
输出:'xm', [object object]
person()就是普通函数的调用,返回值是return后面的内容:'xm' ; new person()是将person作为构造函数调用,返回的永远是对象 ; document.write没法输出对象,它会尝试着将其转换成字符串输出
输出:undefined
call可以改变函数中this的指向,这里在调用方法的时候将其this改为了window,所以this.value就变成了window.value,而window.value没有定义过,所以为undefined
函数的参数:
function add() { if (arguments.length == 0) return; var sum = 0; for (var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } console.log(add()); console.log(add(1, 2, 3, 4, 5));
arguments
类数组,实质是类
function fn(name) { arguments[0] = ''; console.log(name); } fn('xm');//没有输出
arguments.callee 指代函数本身,多用于递归
计算阶乘方法一:
function factorial(num) { if (num <= 1) return 1; return num * factorial(num - 1); } console.log(factorial(5));
计算阶乘方法二:
function factorial(num) { if (num <= 1) return 1; return num * arguments.callee(num - 1); } console.log(jiecheng(5));
计算阶乘方法三:
var jicheng = function fn(num) { if (num <= 1) return 1; return num * fn(num - 1); }; console.log(jicheng(5));
判断传入实参的个数是否与形参相等
arguments.length实参个数
add.length形参个数
function add(num1, num2) { if (arguments.length != add.length) throw new error('请传入' + add.length + '个参数!'); return num1 + num2; } console.log(add(1, 1)); console.log(add(1)); console.log(add(1, 2, 3));
案例:
输出:1,1,1,1,2,3
1、 count()()这样调用,每次都会创建一个新的局部作用域,num的值会不断地被初始化为1
2、 return num++表示先返回num的值,再将num加1
3、 先将count()赋给fn,此时count()只调用了一次,接下来多次调用fn()的时候,count函数并没有多次调用,num只会在count函数调用的时候被初始化,所以多次调用fn()的时候num不会被多次初始化;由于fn相当于count函数的内层函数(var fn=count();这行代码执行后,就调用了count(),调用count后就将里面的函数赋值给了fn,所以说fn就相当于函数的内层函数了。),可以访问count中的变量num,所以多次调用fn函数,会将num的值累加;
推荐阅读
-
Spring中校验器(Validator)的深入讲解
-
C#与js实现去除textbox文本框里面重复记录的方法
-
Java 多线程同步 锁机制与synchronized深入解析
-
Python简单格式化时间的方法【strftime函数】
-
Python3的urllib.parse常用函数小结(urlencode,quote,quote_plus,unquote,unquote_plus等)
-
用MySQL函数清除字符串首尾空白字符的方法
-
user32.dll 函数说明小结
-
深入浅析Java Object Serialization与 Hadoop 序列化
-
深入XPath的详解以及Java示例代码分析
-
深入C++ typedef的用法总结(必看)