JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别

2024-08-27 21:08

本文主要是介绍JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

JavaScript是一种解释型语言,函数声明会在JavaScript代码加载后、执行前被解释,而函数表达式只有在执行到这一行代码时才会被解释。

在JS中有两种定义函数的方式,

1是:var aaa=function(){...}

2是:function aaa(){...} 

var 方式定义的函数,不能先调用函数,后声明,只能先声明函数,然后调用。 

function方式定义函数可以先调用,后声明。

var func=function 和 function func()在意义上没有任何不同,但其解释优先级不同: 后者会先于同一语句级的其他语句。
即: {  var k = xx();  function xx(){return 5;} } 不会出错, 而 {  var k = xx();  var xx = function(){return 5;} } 则会出错。

 

我们来看一下:

var p=function(){}();
这段代码是什么意思。

看了下面这几个例子后,大家就会一目了然了.

var p = function(){return 'abc';}(); alert(p);//abc alert(typeof p); //string
var p = function(){return 111;}(); alert(p);//111 alert(typeof p); //number
现在明白了吧,其实就是定义了一个变量,这个变量是后面函数的返回值。

用Javascript 两大特点,也是JS引擎的实现必然导致的:

1) 返回值。在JS引擎中,所有的语法,操作都有返回值,而且通常返回值是它本身或undefined。通常我们可以用"()"操作符,来获取当前句子的返回值(部分操作符不能用,如var)。例如:a=3;其实这行的返回值就是3,所以在a=b=3时,JS引擎就可以正确的执行下去,首先3赋值给b,然后当前的返回值3再赋值给a(而不是大家所认为的,先将3赋值给b,然后再将b赋值给a)。又例如函数var fun=function(){},当JS引擎执行到这行时,会先执行右边,返回值是一个函数的字面量,然后将这个函数字面量赋值给fun。

Jquery也是利用了这个特性(函数return this),所以才有链式调用。我们看个例子:"fontFamily".replace( /([A-Z])/g, "-$1" ).toLowerCase(),没错这里也是利用了返回值,所以这行的结果是:font-family。

2) 闭包。子函数调用父函数的变量(非传参),就是闭包。在JS中,子函数能访问父函数的变量,这时被引用的变量不会释放,而且子函数中能一直持有这个变量的引用。

结合以上两大特点,可以生成一个力量强大的怪胎:

(function(){})();

不知道专业的名称,我叫它为:立即执行匿名函数。

首先在第一对括号内,是一个匿名函数,第二个括号会立即调用这个匿名函数的返回值,也就是匿名函数中的内容被立即执行。

这个怪胎的强大在于,它独立了一个作用域(括号中内容执行完后会被立即回收),内部变量外部无法访问,而它又能通过this保留字,来访问外部变量。

举个例子:

var i=100; 
(function(){ var j=1; this.plus_ij = function(){  j+=i; alert(j); } 
})(); 
plus_ij();
plus_ij();
上面的例子中,立即执行匿名函数,可以访问到外部变量i,甚至可以var定义一个i(也不会影响外部的i值)。而且内部变量j形成了一个闭包,不会释放。

(function(){ var a = function(){} function b(){} this.c = function(){ a(); b(); } 
})(); 
c();

上面的例子,你会发现,无论哪种定义方式,在立即执行匿名函数外,都无法访问到a和b函数。也就是a和b函数成了这个立即执行匿名函数的内部函数,外部无法调用,除了通过这个立即执行匿名函数内部定义的外部函数。

转自:http://www.cnblogs.com/yongtaiyu/articles/3200722.html



这篇关于JavaScript中Function Declaration与Function Expression 或者说 function fn(){}和var fn=function(){} 的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112785

相关文章

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java进程异常故障定位及排查过程

《Java进程异常故障定位及排查过程》:本文主要介绍Java进程异常故障定位及排查过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、故障发现与初步判断1. 监控系统告警2. 日志初步分析二、核心排查工具与步骤1. 进程状态检查2. CPU 飙升问题3. 内存

java中新生代和老生代的关系说明

《java中新生代和老生代的关系说明》:本文主要介绍java中新生代和老生代的关系说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、内存区域划分新生代老年代二、对象生命周期与晋升流程三、新生代与老年代的协作机制1. 跨代引用处理2. 动态年龄判定3. 空间分

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java内存分配与JVM参数详解(推荐)

《Java内存分配与JVM参数详解(推荐)》本文详解JVM内存结构与参数调整,涵盖堆分代、元空间、GC选择及优化策略,帮助开发者提升性能、避免内存泄漏,本文给大家介绍Java内存分配与JVM参数详解,... 目录引言JVM内存结构JVM参数概述堆内存分配年轻代与老年代调整堆内存大小调整年轻代与老年代比例元空

深度解析Java DTO(最新推荐)

《深度解析JavaDTO(最新推荐)》DTO(DataTransferObject)是一种用于在不同层(如Controller层、Service层)之间传输数据的对象设计模式,其核心目的是封装数据,... 目录一、什么是DTO?DTO的核心特点:二、为什么需要DTO?(对比Entity)三、实际应用场景解析

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

从原理到实战深入理解Java 断言assert

《从原理到实战深入理解Java断言assert》本文深入解析Java断言机制,涵盖语法、工作原理、启用方式及与异常的区别,推荐用于开发阶段的条件检查与状态验证,并强调生产环境应使用参数验证工具类替代... 目录深入理解 Java 断言(assert):从原理到实战引言:为什么需要断言?一、断言基础1.1 语

深度解析Java项目中包和包之间的联系

《深度解析Java项目中包和包之间的联系》文章浏览阅读850次,点赞13次,收藏8次。本文详细介绍了Java分层架构中的几个关键包:DTO、Controller、Service和Mapper。_jav... 目录前言一、各大包1.DTO1.1、DTO的核心用途1.2. DTO与实体类(Entity)的区别1