热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《JavaScript高级程序设计(第二版)》学习(5)函数表达式

声明:这类属于学习笔记,主要是摘录书中内容,比较少的整理。内容经常是跳跃的,建议您阅读书本,收益更大。定义函数的方式有2种,第一种是函数声明,另一种是函数表达式函数声明会提升,就是

声明:这类属于学习笔记,主要是摘录书中内容,比较少的整理。内容经常是跳跃的,建议您阅读书本,收益更大。


 定义函数的方式有2种,第一种是函数声明,另一种是函数表达式

函数声明会提升,就是Javascript引擎先什么都不干,先把函数声明的代码解析一下,那么你是在此之前先用还是后用就无所谓了;但是表达式就没有这种特点,必须在函数表达式之后调用才不会出错。

//这个是可以的
sayhi();
function sayhi(){
    alert("hi");
}

//这种是不行的
sayhi();
var sayhi=function(){
    alert("hi");
};

关于递归:递归因为函数名可能变化,因此一般不会使用函数名,而是使用arguments.collee(n-1)类似这样的方法,但是在严格模式下,是不能获取arguments的,因此可以这么做

//在严格模式下arguments.callee无法通过脚本访问
//可以使用如下方法来代替使用
var fac=(function f(num){
    if(num<=1){
        return 1;
    }else{
        return num*f(num-1);
    }
});

console.log(fac(5));

闭包

有权访问另一个函数作用域中的变量的函数
创建闭包的常见方式使用嵌套函数

当函数第一次被调用时,会创建一个执行环境以及相应的作用域链,并把作用域链赋值给一个特殊的内部属性[[scope]]。然后使用this,arguments和其他命名函数的值来初始化函数的活动对象。但是外部函数的活动对象处于第二位,这样一直到全局执行环境。

在后台的每个执行环境都有一个表示变量的对象——变量对象。全局环境下的变量对象始终存在,而函数内的局部环境的变量对象,在函数执行结束后就消失了。作用域链本质上是一个指向变量对象的指针列表,它只引用但不实际包含变量对象。

然而闭包靠内部定义的函数会将包含函数(外部函数)的活动对象添加到它的作用域链中。当外部函数(不是全局函数的话)执行结束,其执行环境的作用域链会销毁,但活动对象不会回收。

由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,过多使用闭包可能导致内存占用过多。

其次
作用域链的配置机制引起一个闭包的副作用:
只能取得包含函数中任何变量的最后一个值。

function createFunc(){
    var result=new Array();

    for (var i=0; i<10; i++){
        result[i]=function(){
            return i;
        };
    }
    return result;
}

// 得到的函数数组里,i全都10

因为每个函数的作用域链中都保存着外部函数的活动对象,所以他们引用的是同一个变量i,当函数返回result,i的值都是10.

对此我们可以用一种办法强制让闭包符合我们的预期

function create(){
    var result=new Array();

    for(var i=0; i<10; i++){
        result[i]=function(num){
            return function(){
                return num;
            };
        }(i);//立即执行匿名函数并将结果给result
    }
    return result;
}

console.log(create());

闭包里一个经常容易造成问题的是this

匿名函数的执行环境具有全局性,因此this通常是指向window。但因为闭包编写的方式不同,这一点可能会有所不同。

var name="the window";

var obj={
    name:"My object",
    getNameFunc:function(){
        return function(){
            return this.name;
        };
    }
};

console.log(obj.getNameFunc()()); //the window
var name="the window";

var obj={
    name:"My object",
    getNameFunc:function(){
        var that=this
        return function(){
            return that.name;
        };
    }
};

console.log(obj.getNameFunc()()); //my object

在下面这几种特殊情况下this也可能会意外改变

    var name="the window";

    var obj={
        name:"my object",
        getNameFunc:function(){
            return this.name;
        }
    };

    console.log(obj.getNameFunc()); //the object
    var aa=(obj.getNameFunc)(); //the object
    var bb=(obj.getNameFunc=obj.getNameFunc)(); //the window
    console.log(aa+"  "+bb);

    //第一行代码和平常一样调用了对象的方法
    //第二行代码使用了立即执行
    //第三行先是执行了赋值语句,然后调用赋值结果。因为赋值表达式是函数本身
    //所以this不能得到维持,结果就返回了this.window

《Javascript高级程序设计(第二版)》学习(5)函数表达式


推荐阅读
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文介绍了指针的概念以及在函数调用时使用指针作为参数的情况。指针存放的是变量的地址,通过指针可以修改指针所指的变量的值。然而,如果想要修改指针的指向,就需要使用指针的引用。文章还通过一个简单的示例代码解释了指针的引用的使用方法,并思考了在修改指针的指向后,取指针的输出结果。 ... [详细]
  • 在project.properties添加#Projecttarget.targetandroid-19android.library.reference.1..Sliding ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 本文介绍了一种解析GRE报文长度的方法,通过分析GRE报文头中的标志位来计算报文长度。具体实现步骤包括获取GRE报文头指针、提取标志位、计算报文长度等。该方法可以帮助用户准确地获取GRE报文的长度信息。 ... [详细]
  • PDF内容编辑的两种小方法,你知道怎么操作吗?
    本文介绍了两种PDF内容编辑的方法:迅捷PDF编辑器和Adobe Acrobat DC。使用迅捷PDF编辑器,用户可以通过选择需要更改的文字内容并设置字体形式、大小和颜色来编辑PDF文件。而使用Adobe Acrobat DC,则可以通过在软件中点击编辑来编辑PDF文件。PDF文件的编辑可以帮助办公人员进行文件内容的修改和定制。 ... [详细]
author-avatar
徐韵茜YUNXI
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有