1、函数的定义
JavaScript中的函数定义有三种,分别如下:
/** * 函数定义方式一:命名方式/声明式 */ function test_1() { alert("我是命名式函数,或者是声明式函数定义"); } /** * 函数定义方式二:匿名式/引用式函数/函数表达式 */ var test_2 = function() { alert("我是匿名式、引用式或者函数表达式式 的函数定义"); } /** * 函数定义方式三:构造Function对象(直接通过字符串构造函数) */ var test_3 = new Function("arg1","arg2", "alert('我是Function对象构造出来的的方法,参数:'+arg1+','+arg2)"); //test_3的调用方式,如果不传参,则在函数体内获得的参数值将是undefined,多传参数,只前两个有效,不影响功能。 test_3(20,"ttt",200);
注意”声明式函数定义"与"匿名式函数定义"的区别:二者的区别主要在执行的先后顺序上:浏览器加载完js代码后,”声明式函数“代码会在函数执行代码执行之前被解析器解析,而”匿名式函数“定义则是在函数运行中进行动态解析的——不理解?看下面的例子:
/** * 声明式定义函数test */ function test() { alert("one"); } //调用一次 test(); /** * 声明式再定义一遍函数test */ function test() { alert("two"); } //再调用一次 test(); //两次调用的结果都为two,因为“声明式定义函数”的代码先与“执行代码”执行,所以在两次调用test函数时 //test函数的真实函数体是第二次定义后的函数体。
2、函数闭包,一个函数的返回值仍然是一个函数(通俗理解:闭包就是一个函数定义在另一个函数中),例如:
function test() { return test; } //无论调用多少次,最终得到的结果还是函数本身,打印结果将是定义的函数体 alert(test()()()()()()()()()()());
3、一般情况,在JavaScript中,一个函数的形参或者函数体内的局部变量在函数调用完成,执行的返回操作,则全部销毁,不在存在,但是通过闭包,可以让其不销毁,办法如下:
function test(a) { var b = 1; //采用闭包,并且闭包函数内部使用a、b参数,这样a和b参数在函数调用完成后仍不会销毁 return function(x){ return x + a + b; } } //该方法调用结束后,其内容的a、b参数变量不会销毁。 test(100);
4、使用try……catch……finally让函数多次执行return语句。
function test() { var obj = new String("ttttttttttttt"); try { return obj; } catch (ex) { } finally { obj = null; return null; } } //当调用函数,执行多次return语句后,最后得到的结果是最后一次执行return语句的结果。 //以下打印的结果是null alert(test());
5、函数形参和实参
相信任何一个开发人员对于函数的形参和实参的概念都是了如指掌的,不做详述,这里主要要说的是,javascript中函数的实参个数与行参个数没有关系,当实参少于形参时,多余的形参值为undefined,当实参多余形参时,多余部分可以通过Arguments对象来访问。
function test(x, y, z) { } //函数的length属性记录的是函数的形参数量,以下结果打印3,说明test函数有三个形参 alert(test.length)
6、Arguments对象
该对象是任何”函数对象“都拥有的一个属性,记录着调用该函数时传入的实参信息。改变arguments中元素的值,对应的形参值会同步改变,反之亦然。
function test(x, y) { var xcLength = test.length; var scLength = arguments.length; alert("形参的个数为:" + xcLength + ",实参的个数为:" + scLength); var str = ""; for (var i = 0; i < scLength; i=i+1) { str = str + "," + arguments[i]; } alert("你传入的实参值为:" + str); alert("x1="+x); arguments[0] = "呵呵,我变了,x的值也会跟着变,不信你试试!!"; alert("x2="+x); } //调用 test(1, 2, 3, 4, 5, "55555", "OK!");
7、使用Arguments对象模拟实现函数重载
以下函数实现,接收多种不同类型不同数目的实参,模拟函数重载
function test() { var paramsLength = arguments.length; if (0 == paramsLength) { alert("小东西,一个实参都不给,太吝啬!!"); } else if (1 == paramsLength && (typeof(arguments[0]) == "number" || arguments[0] instanceof Number)){ alert("你传入的是Number类型的数据,对不对呀?"); } else if (1 == paramsLength && (typeof(arguments[0]) == "string" || arguments[0] instanceof String)) { alert("呵呵,你传入的是String类型的实参!"); } else if (paramsLength > 1) { throw new TypeError("传入实参过多,该函数不支持!"); } else { throw new TypeError("非法的实参数据类型,该函数不支持!"); } } //执行 try { test(); test(100); test("tttt"); test(100,20,"KKKK"); } catch (e) { alert(e); }
8、Arguments对象的callee属性
该属性被用来引用当前正在执行的函数本身,通过它可以实现一种匿名的递归调用能力,这对于闭包来说非常有用
/** * 递归计算从1加到指定实参值的总和 * 方法一 */ function test1(x) { if (x <= 1) { return x; } else { return x + test1(x -1); } } /** * 方法二 * */ function test2(x) { if (x <= 1) { return x; } else { return x + arguments.callee(x -1); } } //函数调用,计算1+2+3+4+5的值 alert(test1(5));//15 alert(test2(5));//15
callee执行的是函数本身,而this指向的是当前函数的所有者对象,注意区分
function test() { this.x = 100; //打印出来的是函数体本身 alert(arguments.callee); //打印的是一个Object对象引用 alert(this); } //调用 test();
9、下面采用Arguments实现函数的重载机制
首先定义几个不同类型实体类型——交通工具
/** * 定义汽车类 */ function Car(name) { this.name = name; } /** * 重写汽车类的toString方法 */ Car.prototype.toString = function() { return "汽车牌号:" + this.name; } /** * 定义飞机类 */ function Plane(name) { this.name = name; } /** * 重写飞机类的toString方法 */ Plane.prototype.toString = function() { return "飞机编号:" + this.name; } /** * 定义轮船类 */ function Boat(name) { this.name = name; } /** * 重写轮船类的toString方法 */ Boat.prototype.toString = function() { return "轮船标号:" + this.name; }然后定义一个能够,根据不同的参数,动态调用不同的方法的方法
/** * 匹配参数类型和参数值,自动调用符合条件的重载函数 * * @param func 将要被调的函数 * @param func 参数类型与值的映射 * @param func 函数所有者 */ function callOverloadMethod(func, argMaps, owner) { owner = owner || null; var args = []; for (var i = 0; i < argMaps.length; i++) { if (argMaps[i].type != typeof(argMaps[i].arg) && !(argMaps[i].arg instanceof argMaps[i].type)) { return; } else { args.push(argMaps[i].arg); } } return func.apply(owner, args); }定义一个存在重载方法的函数
/** * 定义一个司机类,用于开各种交通工具 * * @param dirverName 司机姓名 * @param meansOfTransportation 交通工具类 */ function Driver(dirverName, transportationTool) { this.diverName = dirverName; this.doing = ""; /** * 开汽车 * @returns {driverCar} */ function driverCar(car) { this.doing = "【"+this.diverName + "】正在开汽车," + car; } /** * 开飞机 * @returns {driverPlane} */ function driverPlane(plane) { this.doing = "【" + this.diverName + "】正在开飞机," + plane; } /** * 开轮船 * @param boat */ function driverBoat(boat) { this.doing = "【" + this.diverName + "】正在开轮船," + boat; } /** * 参数不够时的默认处理方法 */ function doNothing() { this.doing = "你传给的参数不够,我不知道做什么,我勒个去…………"; } /** * 表示参数类型与值的映射类 * * @param type * @param arg * @returns {___anonymous5119_5138} */ function toolType(type, arg) { return {type:type, arg:arg}; } //方法——数据类型——参数的映射关系 var funcs = [ [driverCar, [toolType(Car, transportationTool)]], [driverPlane, [toolType(Plane, transportationTool)]], [driverBoat, [toolType(Boat, transportationTool)]] ]; //开始实现司机的实际处理业务逻辑,如果连司机都没有指定,则默认交给队长开飞机 if (0 >= arguments.length) { Driver.call(this, "队长", new Plane("空军一号")); //仅指定了司机 } else if (1 == arguments.length) { this.doNothing(); //如果既指定了司机,又指定了交通工具,则根据不同的交通工具调用不同的处理方法 } else if (2 == arguments.length) { for (var i = 0; i < funcs.length; i=i+1) { try { callOverloadMethod(funcs[i][0], funcs[i][1], this); } catch (ex) { alert(ex); } } } else { throw new Error("参数过多,系统不接受!"); } } /** * 重写Driver类的toString方法 */ Driver.prototype.toString = function() { return this.doing; }最后测试:
相关推荐
JavaScript函数式编程是利用JavaScript语言编写函数式风格代码的一种编程范式。函数式编程强调使用纯函数、避免副作用、函数的不可变性以及利用高阶函数等概念。通过阅读《JavaScript函数式编程指南》,读者可以了解...
不过,由于【标题】中提供了文档的名称——"JavaScript函数式编程.pdf",我可以根据这个名称扩展出关于JavaScript函数式编程的知识点。 JavaScript函数式编程的知识点非常丰富,涉及很多方面的内容,下面将详细介绍...
C#与JAVASCRIPT函数的相互调用 C#调用JAVASCRIPT函数的调用 JAVASCRIPT调用C#函数的调用
JavaScript函数是编程语言的核心组成部分,它是一段可重复使用的代码块,可以接受参数并返回值。在JavaScript中,函数不仅可以作为表达式,还能作为变量赋值、作为参数传递以及作为返回值。本速查指南将深入探讨...
JavaScript函数是编程语言的核心组成部分,尤其在Web开发中起着至关重要的作用。这份"JavaScript函数速查手册"涵盖了JavaScript函数的各个方面,旨在帮助开发者快速查找和理解各种函数的用法和特性。 一、函数基础 ...
- 这里的回调函数用于处理JavaScript函数的异步返回结果,如果需要同步获取结果,可以使用`QWebEngineScript`来注册一个全局JavaScript对象,然后通过该对象调用JavaScript函数。 2. **JavaScript调用QT函数**: ...
以下是关于JavaScript函数的详细讲解: 1. **函数定义**: - 无参函数定义:`function 函数名 () { 代码... }` - 有参函数定义:`function 函数名 (参数列表) { 代码... }` - 参数列表中的参数可以是变量、常量...
JavaScript函数式编程是一种编程范式,它将计算视为数据处理,并强调使用无副作用的纯函数。在JavaScript中,函数式编程允许我们写出更简洁、可读性更强的代码,同时提高了代码的复用性和测试性。《JavaScript函数式...
JavaScript函数式编程是一种编程范式,它强调使用函数来组织代码,将计算视为一系列惰性求值的操作。Underscore.js是一个轻量级的JavaScript实用库,它为开发者提供了大量函数式编程工具,使得在JavaScript中实践...
JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)JavaScript函数(源代码)...
JavaScript函数式编程是一种编程范式,它强调将计算视为对数据进行操作的纯函数,而不是通过改变状态或显式指令来控制程序流程。在JavaScript中,函数式编程可以帮助我们写出更简洁、可读性强且易于测试的代码。下面...
JavaScript函数式编程
而《JavaScript函数式.zip》可能是一份关于JavaScript函数式编程的资料集合,函数式编程是一种编程范式,强调使用函数和避免改变状态。其中可能涵盖以下知识点: 1. **纯函数**:理解纯函数的定义,即给定相同的...
第7节 JavaScript函数及应用.rar第7节 JavaScript函数及应用.rar第7节 JavaScript函数及应用.rar第7节 JavaScript函数及应用.rar第7节 JavaScript函数及应用.rar第7节 JavaScript函数及应用.rar第7节 JavaScript函数...