《python全栈工程师 - web开发前端基础》:javascript函数

    技术2022-07-11  112

    《python全栈工程师 - web开发前端基础》:javascript函数

    课程目标详情解读1.1函数的基本定义1.2 默认参数位置不限制、按照顺序传参1.3参数列表-arguments,通过传参顺序索引0,1,2,3...取值1.4匿名函数-函数表达式,可以将匿名函数赋值给一个变量2.1不支持重载:javascript定义多个同名函数,只有最后一个生效2.2作用域2.3嵌套函数与闭包2.4函数作为参数2.5 高阶函数2.5.2 this

    课程目标

    函数的基本定义作用域嵌套函数与闭包高阶函数callee与this

    详情解读

    1.1函数的基本定义

    函数声明: function funcName(args1, args2) { … … return… } 函数调用传参时可以传递不限数量的参数,在函数内部使用arguments对象接受 函数表达式: funcName = function (args1, args2) { … … return… } 使用函数声明与使用函数表达式定义的区别: 函数声明会在调用之前已经加载好 函数表达式只有执行到该行代码时才会定义函数

    // 函数声明式定义方式 function myFun(){ console.log("hello world") } //函数调用 myFun() // 函数参数 function mySub(a, b){ console.log("a=>",a ," b=>", b) return a-b } // // 传参调用 // // 顺序传参 // mySub(10,2) // //不支持关键字传参 mySub(b=2, a=10)

    运行结果:(注意js是不支持关键字传参的,不要被mySub(10,m=2)迷惑)

    1.2 默认参数位置不限制、按照顺序传参

    function myFun(a, c, b=2, d){ console.log("a=>", a, " b=>", b, " c=>", c, " d=>", d) } a = 10, b = 2 myFun(10) a = 10, c = 20, b = 2 myFun(10, 20) a = 10, c = 20, b = 30 myFun(10,20,30) a = 10, c = 20, b = 30, d = 40 myFun(10,20,30,40)

    1.3参数列表-arguments,通过传参顺序索引0,1,2,3…取值

    function myFun(a,b){ console.log(a) console.log(b) console.log(arguments) console.log(arguments[0]) //a console.log(arguments[0]) //b } myFun(1,20) myFun(1,2,3,4,5,6) function myStudents(){ console.log(arguments) if (arguments[0]!=undefined){ console.log("您的名字:",arguments[0] ) } if (arguments[1]!=undefined){ console.log("您的性别:",arguments[1] ) } } myStudents("luxp") myStudents("luxp", "男")

    1.4匿名函数-函数表达式,可以将匿名函数赋值给一个变量

    使用函数声明与使用函数表达式定义的区别 函数声明会在调用之前已经加载好 函数表达式只有在执行到该行代码时才会定义函数

    my_func = function(){ console.log(arguments) } my_func() myHello1() // 这句正常执行,因为函数声明会在调用之前已经加载好 myHello2() // 这句会报错,因为匿名表达式只有执行到该行代码时才会定义函数 function myHello1(){ console.log("hello") } myHello2 = function(){ console.log("hello") } // 下面两句都可以正常执行 myHello1() myHello2()

    2.1不支持重载:javascript定义多个同名函数,只有最后一个生效

    function myfun(a){ console.log("1") } function myfun(a,b){ console.log("2") } function myfun(a,b,c){ console.log("3") }

    2.2作用域

    在web浏览器中,全局环境表示为窗口window对象下 所有的全局变量与函数都是window的属性或者方法 关闭浏览器窗口,就销毁了所有的全局对象 每个函数都拥有自己的执行环境 每一个代码执行时都有自己的作用域链,作用链前端就是当前执行环境的变量对象,作用域链下一个变量对象就是下一个包含的环境,直到全局环境

    在另一个窗口的运行:

    在函数内部使用var定义的变量为函数内部变量, 如果没有使用var关键字,变量就会声明为全局变量。 es5规范中并没有块级作用域,即诸如if, while的{}部分,es6拥有块级作用域

    my_sex= "男" function myFun(){ var my_name = "luxp" // 此处my_name是局部作用域的变量,外部不能访问;如果没有用var,则是全局作用域的变量,外部可以访问 my_age = 18 console.log(my_name, my_sex) } myFun() console.log(my_name)

    变量作用域查找顺序由内而外寻找,当在函数内部定义局部变量时,首先会声明该变量

    var name = "luxp" function seekName1(){ var name = "luxp_2" console.log(name) // 输出 luxp_2 var name = "luxp_1" function subFun(){ var name = "luxp_3" // name = "luxp_4" console.log(name) // 输出 luxp_3 } subFun() } seekName1() //局部变量会被预先声明 function seekName2(){ console.log(name) // 输出全局变量中的name,为 luxp // 如果用var声明name,则上面的语句打印结果为undefined,是相当于在打印name之前声明了局部变量name // var name = "luxp_2" // var name = "luxp_1" function subFun(){ var name = "luxp_2" // name = "luxp_4" console.log(name) // 输出局部变量中的name,为luxp_2 } subFun() } seekName2()

    2.3嵌套函数与闭包

    function funcParent() { funcChild() { } return funcChild() }

    将函数作为值返回 示例代码:

    function create_fun(I){ return function (){ return "func_"+I } } func_array = [] for (i=0;i<5;i++){ func_array[i]=create_fun(i) }

    如何让每个函数输出不同的值

    /* 闭包的原因,所有的函数都会输出five */ function create_fun(){ var array=['one','two','three','four','five'] var func_array=[] for(i in array){ console.log(i) func_array[i]=function(){ return array[i] } } return func_array } //执行这一句的时候,内部函数其实是引用i,而不是i的值,执行 //到最后的时候i的值是4,所以全部的函数的i都是5 func_array=create_fun() func_array[0]()

    function create_fun(){ var array = ["one", "two", "three", "four", "five"] var func_array = [] for (i in array){ func_array[i] = function create_fun(I){ //增加了一个内嵌函数 return function (){ return array[I] } //执行,通过执行把i的值固定下来 }(i) } return func_array } func_array = create_fun() func_array[0]()

    2.4函数作为参数

    函数可以作为一个参数给另一个函数调用,另一个函数就被称为该函数的高阶函数

    示例代码:

    function sum(a,b){ return a+b } function sub(a,b){ return a-b } function compute(func, a,b){ return func(a,b) } value = compute(sum, 10,3) value = compute(sub, 10, 3) function selectEvenNumber(number){ if (number % 2 == 0) { return number } else { return 0 } } function selectOddNumber(number){ if (number % 2 == 1) { return number } else { return 0 } } function map(array, func=selectEvenNumber){ for ( i in array){ array[i] = func(array[i]) } } array = [1,2,3,4,5,6,7,8,9] map(array) console.log(array) array = [1,2,3,4,5,6,7,8,9] map(array, selectOddNumber) console.log(array) /* js中常见的一种高阶用法 */ function myfun(args, func){} myfunc(args, function(){})

    运行结果:

    2.5 高阶函数

    function func1(){} function func2(func){ return func() } return func2(func1)

    2.5.1 callee与this

    arguments.callee可以在内部对函数名实现解耦 callee代表这对函数自身的引用,可以降低函数名与内部调用的耦合性

    示例代码一:

    function myFun(){ console.log(arguments) console.log(arguments.callee) }

    运行结果: 示例代码二:

    /*利用递归计算阶乘 */ // 这种方法,当函数名改变时,函数内部的递归方法名也得修改 function jiecheng(num) { if (num === 1) { return 1 } else { return num * jiecheng(num-1) } } // 这种方法不一样,无论函数名如何改变,函数内部的递归方法名不用修改 function jiecheng(num) { if (num === 1) { return 1 } else { return num * arguments.callee(num-1) } }

    2.5.2 this

    在函数内部,this引用了函数的执行环境

    /* this 指向对象由所在的执行环境决定 */ console.log(this) function myFun(){ console.log(this) // return this this.nickname = "luxp" } function myFun(){ function mySubFun(){ console.debug(this) return this } return mySubFun() } function myFun(){ var o = new Object() o.func = function(){ console.log(this) } return o }

    Processed: 0.008, SQL: 9