函数相关

函数

1. 函数基础

基础结构:

function test(a, b) {
    // 执行语句
}

// 例子
if(a > 3) {
    for(var i = 0; i< 10; i++) {
        console.log(i)
    }
}
if(a > 2) {
    for(var i = 0; i< 10; i++) {
        console.log(i)
    }
}
if(a > 1) {
    for(var i = 0; i< 10; i++) {
        console.log(i)
    }
}

上面代码重复代码过多,耦合高

我们编程的主要思想就是高内聚 低耦合

高内聚: 开发的一个功能模块,相关性联系性强,独立性强

低耦合:我们希望把重复的代码抽象出来,组成一个独立的功能体去完成独立的功能

解耦合:—》函数

2. 函数的组成部分和声明

函数的最基本的写法:函数声明

function test(arguments || c参数) {
    // 函数的执行语句
}

test()// 函数的调用

3. 函数的参数与形实参的映射关系

例如:

function test() {
    var a = 1,
        b = 2;
    console.log(a + b)
}
test();
// 此时 a, b均为定值 我们创造一个函数 不希望值是固定的
// 这时候我们可以需要参数
             // 占位 形式上占位
function test(a, b) {
    console.log(a + b)
}
//    实参
test(1, 2)
// a, b 可以理解为函数内部声明的变量(类似于), 用户可以传入需要的值
// 区别在于参数可以在函数调用的时候赋值, 而函数内部变量无法在函数执行的时候赋值
// a=>1, b=>2 参数一一对应
// test(NaN, false) 参数没有特定的类型
function test(a, b, c) {
    console.log(a, b, c)
}
test(1, 2)//会不会报错?1, 2 undefined
test(1, 2, 3, 4)// 1, 2, 3
// 当实参和形参数量可以不等,

// 问题 是否能够知道有哪些实参
function test(a, b) {
    consoe.log(test.length);// 形参个数
    console.log(arguments.length);// 实参个数
    console.log(arguments[1]) // 2 可以取到第几位是什么
}
test(1, 2);
// [1, 2]

// 小栗子
// 一个函数被执行的时候, 累加他的实参
function test() {
    var a = 0;
    for(var i = 0; i < arguments.length; i++) {
        a += arguments[i];
    }
    console.log(a)
}
test();


// 问题
function test(a, b) {
    a = 3
    console.log(arguments[0]);// 3
}
test(1, 2);
// 改变实参 可以在函数内部更改实参的值

function test(a, b) {
    b = 3
    console.log(arguments[1]);// undefined
}
test(1);
// 实参中没有传递b的值 函数内部会不会打印出来b?
// 不会 实参中没有传递值 b就是undefined, 给未被定义的形参赋值
// 实参打印不出来
// 总结: 如果实参内有值可以在函数内部重新赋值, 如果实参内没有,函数内部再去更改是没有用的


思考:

// 以下函数, 形参a = 3 , arguments[0] = 3; 两者变量是不是同一个东西?
// 映射关系  arguments数组中有形参的变量,会形成映射关系一一对应
function test(a, b) {
     a = 3// 栈内存
     console.log(arguments[0]);// 堆内存存储数组,栈内存存储地址
}
test(1, 2);

4. 函数参数默认值

// 初始化参数 默认值:如果没有设置就是undefined
function test(a, b) {
    console.log(a, b)// 1, undefined
}
test(1)

// 如果不传实参还想要他有默认值

function test(a = 1, b = 2) {
    console.log(a, b)// 1, 2
}
test()undefined

function test(a = 1) {
    console.log(a, b)// 1, undefined
}
test()

// 问题 a为默认值, b怎么传递?
function test(a = 1) {
    console.log(a, b)// 1=》2, undefined
}
test(2)// 此时修改的时a的默认值

function test(a = 1) {
    console.log(a, b)// 1, 2
}
test(undefined, 2)
// 如果形参传值, 实参为undefined, 默认找形参的值
// 实参非undefined 形参undefined 默认找实参的值
// 形参内赋值 低版本浏览器不兼容 ES6写法

// 曲线救国===>等同于形参内赋值
function test(a, b) {
    var a = arguments[0] || 1;
    var b = arguments[1] || 1;
}
test();

5. 函数的返回值

// 终止函数执行
function test() {
    console.log('我正在执行');
    console.log('我执行完了这个函数');
    // return 隐式添加 终止函数执行
}
test();
// return 之后语句不会执行

// 返回值
function test(name) {
    if(!name) {
        return '1';
    }else {
        return name;
    }
}
test('zs');


6. 全局变量与函数

a = 1;
function test() {
    var b = 1;
    console.log(a);//1
}
test();
console.log(b);// a is not defined


a = 1;
function test1() {
    var b = 2;
    console.log(a);// 1
    function test2() {
        var c = 3;
        console.log(b);// 2
    }
    test2();
    console.log(c)// c is not defined
}
test1();

// 里面变量可以访问外面变量, 外面无法访问里面的
// b, c局部变量[[scope]]

function test1() {
    var a = 1;
    console.log(b)
}

function test2() {
    var b = 2;
    console.log(a)
}
test1();
test2();
// 变量访问的范围

一个固定的功能或者程序, 被封装的过程, 实现一个固定的功能或者程序,在这个封装体需要一个入口和一个出口, 入口就是参数, 出口就是返回。

7. 函数递归

// n的阶乘不能用for
// n! = n * (n - 1)
function fact(n) {
    if(n === 1) {
        return 1;
    }
    return n*fact(n-1);
}
// 函数自己调用自己 性能差 慎用
// 黄金分割数列
// 1, n3 = n2 + n1;
// 2. n <= 2
function fb(n) {
    if(n <= 0) {
        return 0;
    }
    if(n <=2 ) {
        return 1
    }
    return fb( n - 1 ) + fb(n - 2)
}

8. 立即执行函数

当一个函数在一个页面开始就调用 而且只使用这么一次的话,一般函数还继续存在GO中

  • 自动执行
  • 执行之后立即释放

IIFE:immediately-invoked function expression

初始化函数: 最好用立即执行函数

(function() {}());// w3c建议
(function() {})();// 常用

(function() {
    var a = 1,
        b = 2;
    console.log(a + b) // 3
})()

(function test() {
    var a = 1,
        b = 2;
    console.log(a + b) // 3
})()
// test is not defined
// 函数执行完立即销毁

(function(a, b) {
    console.log(a + b) // 3
})(1, 2)
// 可以传参

var add = (function(a, b) {
    return a + b
})(1, 2)
console.log(add);// 3

// 注意括号包起来的都是表达式

// 思考一下函数会不会执行?
function test() {
    
}()
// 不会 语法错误

var test = function() {
    
}()
// 可以执行

// 什么时候加括号会执行不会报错
// 一定是表达式才能被括号执行


var test = function() {
    console.log(1);
}
console.log(test);// function

var test = function() {
    console.log(2);
}()
console.log(test);// 2 undefined
// 立即执行 执行完后销毁
// 函数声明变成表达式的方法 + - ! || &&
// 接括号就会执行 该函数函数名自动会忽略
function test(a, b) {
    console.log(2)
}(1)// 不会执行 优先解析括号内表达式

// 逗号运算符
(1, 2)// 返回逗号后面的值 ===》2

9. callee与caller

function test(a, b, c) {
    console.log(arguments.callee.length)//3当前arguments所指向的函数test 在哪函数里指向哪个函数
    console.log(test.length)// 3
}
test(1, 2, 3)// 3

// 找不到函数名情况下 递归
var sum = (function() {
    if(n<=1) {
        return 1;
    }
    return n + arguments.callee(n - 1);
})(10)

//caller
// 严格模式报错 caller callee
function test1() {
    test2()
}
function test2() {
    console.log(test.caller)// 谁调用了test2 就返回哪个函数
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值