JavaScript函数

本文详细介绍了JavaScript中的函数定义、函数表达式、函数执行、作用域、预编译、立即执行函数以及闭包的概念和应用。通过实例解析了形参与实参的匹配、变量提升以及闭包在内存管理中的影响。此外,还讨论了JavaScript运行的三个阶段和闭包在实现公有变量、函数累加器以及内存优化等方面的作用。
摘要由CSDN通过智能技术生成

函数

定义

  • 函数声明
function 函数名() {} //定义函数
函数名(); //执行函数

函数名 / 变量名中, 多个单词拼接时, 第一个单词首字母小写, 第二个单词及后面的单词首字母大写

  • 函数表达式
var 变量名 = function 函数名() {} // 命名函数表达式
var 变量名 = function () {} //匿名函数表达式, 函数名为变量名, 更常用, 直接称为函数表达式
函数名();

只有表达式才能被执行符号执行; 能被执行符号执行的函数表达式, 函数的名字会被自动忽略 (变为立即执行函数).

组成形式

  1. 函数名称

  2. 参数

  • 形式参数
function sum(a,b){
    var c = a + b;
    document.write(c);
}
  • 实际参数
sum(1,2);

形参与实参个数不一时不报错, 实参会被自动列入arguments[]形成实参列表(数组)

  1. 返回值

终止函数, 不写时默认在函数最后, return;后面的函数不执行.

function sum(){
    return 123;
}
var num = sum(); //返回123

作用域

作用域定义: 变量 (变量作用域又称上下文) 和函数生效 (能被访问) 的区域.

全局变量和局部变量: 定义在函数外的变量问全局变量, 定义在函数内的变量为局部变量.

1.里层可以访问外层的变量, 外层不能访问里层的变量.
2.彼此独立的函数不可以互相访问变量.
3.全局变量都可以被访问.

[[scope]]: 每个JavaScript函数都是一个对象,对象中有些属性我们可以访问, 但有些不可以, 这些属性仅提供JavaScript引擎存取, [[scope]]就是其中一个.
[[scope]]指的就是我们所说的作用域, 其中存储了执行期上下文的集合.

作用域链: [[scope]]中所存储的执行期上下文对象的集合, 这个集合程链式链接, 我们把这种链式链接叫做作用域链.

执行期上下文: 当函数执行时, 会创建一个称为执行期上下文的内部对象.一个执行期上下文定义了一个函数执行时的环境, 函数每次执行时对应的执行上下文都是独一无二的, 所以多次调用一个函数会导致创建多个执行上下文, 当函数执行完毕, 它所产生的执行上下文被销毁.

查找变量: 从作用域链的顶端依次向下查找.

递归

  1. 找规律
  2. 找出口

立即执行函数

定义: 此类函数没有声明, 再一次执行过后即释放. 适合做初始化工作.

(function (){}());w3c建议
(function (){})();

    (function abc() {
        var a = 123;
        var b = 234;
        console.log(a + b);
    }())

    (function (a,b,c) {
        console.log(a + b + c * 2);
    }(1,2,3))

    // !/+/-
    ! function test() {
        console.log('a');
    }();
    //执行一次后再次查找会报错
    function (a, b, c){
        console.log('a');
    }();
    //报错

    function (a, b, c){
        console.log('a');
    }(1, 2, 3);
    //不报错也不执行

js运行三部曲

语法分析 (语义分析)

通篇扫描但不执行

预编译

预编译发生在函数执行的前一刻

特点:

  • 函数声明整体提升

函数声明整体永远提升到最前面

  • 变量 声明提升

变量的声明永远提升到最前面, 但赋值不提升

预编译前奏
  1. imply global 暗示全局变量: 及任何变量, 如果变量未经声明就赋值, 此变量就为全局对象(window)所有.
    a = 10;
    window.a = 10;
    console.log(a) = undefined;
    var a = b = 123;
    window.b = 123; //b未经声明存于window中
    window.a = undefined;
  1. 一切声明的全局变量, 全是window的属性.
    var a = 123;
    window.a = 123;
    function text(){
        var a = 123;
    }
    text();
    window.a = undefined;

window就是全局

四部曲
  1. 创建AO对象 Activation Object (执行期上下文)

全局为GO对象 Global Object

  1. 找形参和变量声明, 将变量和形参名作为AO属性名, 值为undefined

  2. 将实参值和形参统一

  3. 在函数体里面找函数声明, 值赋予函数体

解释执行

执行代码

闭包

当内部函数被保存到外部时, 将会生成闭包. 闭包会导致原有作用域链不释放, 造成内存泄露.

重要示例:

    function test() {
        var arr = [];
        for(var i = 0; i < 10; i ++){
            arr[i] = function () {
                document.write(i + " ");
            }
        }
        return arr;
    }
    var myArr = test();
    for(var j = 0; j < 10; j++) {
        myArr[j]();
    }
    //输出: 10 10 10 10 10 10 10 10 10 10 
    function test() {
        var arr = [];
        for(var i = 0; i < 10; i ++) {
            (function (j) {
                arr[j] = function () {
                    document.write(j + " ");
                }
            }(i));
        }
        return arr;
    }
    var myArr = test();
    for(var j = 0; j < 10; j ++) {
        myArr[j]();
    }
    //输出: 0 1 2 3 4 5 6 7 8 9

闭包的作用

  1. 实现公有变量
  • 函数累加器
var count = 0;
function test() {
    count ++;
    console.log(count);
}
test(); // -- 1;
test(); // -- 2;
test(); // -- 3;
test(); // -- 4;
function add() {
    var num = 0;
    function a() {
        console.log(++num);
    }
    return a;
}
var myAdd = add();
myAdd(); // -- 1;
myAdd(); // -- 2;
myAdd(); // -- 3;
  1. 可以做缓存 (存储结构)
function test() {
    var food = "apple";
    var obj = {
        eatFood : function () {
            if(food != "") {
                console.log("I am eating " + food);
                food = "";
            }else {
                console.log("There is nothing!");
            }
        },
        pushFood : function (myFood) {
            food = myFood;
        }
    }
    return obj;
}
var person = test();
person.eatFood(); // -- I am eating apple
person.eatFood(); // -- There is nothing!
person.pushFood('banana');
person.eatFood(); // -- I am eating banana
  1. 可以实现封装, 属性私有化

  2. 模块化开发, 防止污染全局变量.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值