在前一章中讲了JavaScript的入门语法,在这一章要看看函数的使用。

函数的定义

JavaScript中的函数和Python中的非常类似,只不过定义的方式有些不同,下面看看是怎么定义的

//定义普通函数
function f1(){
console.log('hello world!')
} //定义带参数的函数
function f2(a,b){
console.log(a)
console.log(b)
} //定义带返回值的函数
function f3(a,b){
return a+b
} //定义匿名函数
var sum = function(a,b){
return a+b
} //定义立即执行函数
(function(a){
console.log('立即执行函数')
})(a)

立即执行函数其实有些像python里的lambda方法,的用法应该注意一下:因为在我们在全局内定义了一个变量,在定义函数的过程是无法调用这个变量的。

(function(a,b){
console.log(a+b);
console.log('函数中')
})(123,456)

这个方法可以让外部访问不到函数中的变量,防止函数污染全局变量。

函数的调用

这里要将一个JavaScript里比较随意的一点(也可以说是一个坑),我们看一看下面的函数

function fun(a,b){
console.log(a+b);
} fun(12,34)

这样没啥问题,因为形参和函数调用的时候的实参数量是一致的。那么我们改一下实参的状态,会怎么样?

fun(12,34,56)
//打印值为46
fun(12)
//打印值为NaN

arguments的使用

这里就要讲到arguments的使用了,类似Python中的*args,arguments表达了函数的形参(但是是可以不用在声明函数中明确的写出来的)

所以在JS的函数里不管是多传参数或少传参数都是不会报错的,我们可以这样看看

function fun2(a,b){
console.log(arguments)
for (i=0;i<arguments.length;i++){
console.log(arguments[i])
}
} fun2(11,22,33,44)

而我们想要算一下传入参数的累加值,就要按下面的方法了

function fun_sum(a,b){
var totle=0;
for (i=0;i<arguments.length;i++){
totle += arguments[i]
}
return totle
} console.log(fun_sum(1,2,3,4,5))
 函数的全局变量和局部变量

局部变量

在JavaScript内部声明的变量(var)是局部变量,所以只能在函数内部访问,就是说这个变量的作用域只有函数内部。只要函数运行完毕,改变量就会被删除。

全局变量

在函数外部声明的变量是全局变量,网页上所有的脚本和函数都能访问。

var test = 'test'

console.log('声明函数前',test)
function fun(){
console.log('开始声明函数',test);
var test = 'in func';
console.log('函数声明完成',test);
} console.log('调用函数前',test);
fun();
console.log('调用函数后',test); //////////输出//////////
声明函数前 test
调用函数前 test
开始声明函数 undefined
函数声明完成 in func
调用函数后 test

注意这里还有个非常坑的点:

我们在定义函数前有个变量test,如果在函数内部没有对这个test进行赋值,那么这个变量是正常的,但是一旦有了赋值操作,在操作前就成了underfined了(上面的例子就是有了赋值操作),在看看下面的

var test2 = 123;
function fun2(){
console.log(test2)
} fun2() //////////输出//////////
123

变量生存周期

JavaScript的变量生命期从他们被声明的时候开始,

局部变量是在函数运行结束的时候被删除,而全局变量是在页面被关闭的时候删除。

作用域

还是要看看这几个例子:

例子1

var city = 'beijing';
function fun(){
var city = 'shanghai';
function inner(){
var city = 'shenzhen';
console.log(city);
}
inner();
} fun()
////////输出////////
shenzhen

例子2

var city = 'beijing';
function fun(){
console.log(city);
} function fun2(){
var city = 'shanghai';
return fun;
} var ret = fun2();
ret();
//////////输出//////////
beijing

案例3.闭包

var city = 'beijing';
function f(){
var city = 'shanghai';
function inner(){
console.log(city);
}
return inner;
} var ret = f();
ret() //////////输出//////////
shanghai

在上面的例子中,ret对应的函数就是inner(),也就是闭包的用法。

所以,函数的调用一定要往回找函数的定义过程。

首先,在函数内部找->再往外部找,最后找全局作用域。

词法分析

JavaScript在调用函数的一瞬间,会先进行词法分析,大致过程是这样的:

函数调用的前一个瞬间,回显形成一个激活对象:Active Object(AO),并会进行下面3个方面的分析

  函数参数——如果有参数,则将此参数赋值给AO,且值为underfined;如果没有,则不做任何操作。

  函数局部变量——如果AO上右同名的值,则不做任何操作,如果没有,则将此变量赋值给AO,并且值为underfined。

  函数声明——如果AO上有,则会将AO上的对象覆盖,如果没有则不做任何操作。

  综上所述,函数内部无论是使用参数还是使用局部变量都会到AO上找。

再看看下面的例子:

var name = 'xiaoming';
var age =12;
function fun(){
console.log(age);
var age = 30;
console.log(age)
} fun() //////////输出//////////
underfined
30

这也就是讲了上面的那个坑是怎么导致的。

 var age =12;
function fun(){
console.log(age);
var age = 22
console.log(age)
function age(){
console.log('inner func');
}
console.log(age)
}
fun()
//////////输出//////////
ƒ age(){
console.log('inner func');
}
22
22

结合前面的规则看看是怎么执行的。

首先是分析过程:

  1.检查函数内是否有参数——没有

  2.检查函数内是否有局部变量——第4行的代码,定义了age局部变量,然后使AO.age=underfined

  3.检查函数内是否有内置函数——第6行的代码定义了局部函数age,然后覆盖原AO.age=fun()

然后是执行阶段

  1.要记得,所有的值都是从AO里找的,第3行的打印就是打印的AO.age,实际值应为fun().

  2.第4行的代码是AO.age值赋值为22,后面再打印就是22了。

JavaScript入门学习之二——函数的更多相关文章

  1. JavaScript入门-学习笔记(二)

    关于js变量 变量,就是一个用来存储数据的容器 一般来说,我们的变量都是可以得先声明,再使用,就像是一个东西先必须存在,才能看得见摸得着.然而在js里(es5),可以先使用,后声明. a = 100; ...

  2. python入门学习:7.函数

    python入门学习:7.函数 关键点:函数 7.1 定义函数7.2 传递实参7.3 返回值7.4 传递列表7.5 传递任意数量的实参7.6 将函数存储在模块中 7.1 定义函数   使用关键字def ...

  3. 【转载】salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句

    salesforce 零基础开发入门学习(二)变量基础知识,集合,表达式,流程控制语句 salesforce如果简单的说可以大概分成两个部分:Apex,VisualForce Page. 其中Apex ...

  4. React Native小白入门学习路径——二

    万万没想到,RN组仅剩的一个学长也走了,刚进实验室没几天就被告知这样的事情,一下子还真的有点接受不了,现在RN组就成了为一个没有前辈带的组了,以后学习就更得靠自己了吧.唉,看来得再努力一点了. 这一周 ...

  5. MyBatis入门学习(二)

    在MyBatis入门学习(一)中我们完成了对MyBatis简要的介绍以及简单的入门小项目测试,主要完成对一个用户信息的查询.这一节我们主要来简要的介绍MyBatis框架的增删改查操作,加深对该框架的了 ...

  6. JavaScript正则表达式学习笔记(二) - 打怪升级

    本文接上篇,基础部分相对薄弱的同学请移步<JavaScript正则表达式学习笔记(一) - 理论基础>.上文介绍了8种JavaScript正则表达式的属性,本文还会追加介绍几种JavaSc ...

  7. Java Web入门学习(二) Eclipse的配置

    Java Web学习(二) Eclipse的配置 一.下载Eclipse 1.进入Eclipse官网,进行下载 上图,下载Eclipse IDE for JaveEE Developers 版本,然后 ...

  8. Swoole 入门学习(二)

    Swoole 入门学习 swoole 之 定时器 循环触发:swoole_timer_tick    (和js的setintval类似) 参数1:int $after_time_ms 指定时间[毫秒] ...

  9. JavaScript入门-学习笔记(一)

    JavaScript入门(一) 学习js之前,我们先来了解一下,什么是JavaScript? JavaScript是一种解释型语言.在运行的时候,一边读一边编译一边执行.简单来说就是,在执行js代码时 ...

随机推荐

  1. D3画完整柱状图(带坐标轴、标签)

    昨天晚上本来打算花一点时间把之前学的柱状图改一下,用CSV文件来替换自定义数据.这一替换可不得了,一晚上就搭进去了,还好今早找到了问题的所在,原因在于我的数据引用出了问题. 现在就来讲解一下如何画一个 ...

  2. 添加SSH keys到github帐号

    使用git clone命令从github上同步github上的代码库时,如果使用SSH链接(如我自己的esesgrid项目:git@github.com:hmilycc/esesgrid.git),而 ...

  3. 一文搞懂 Java 中的枚举,写得非常好!

    知识点 概念 enum的全称为 enumeration, 是 JDK 1.5 中引入的新特性. 在Java中,被 enum关键字修饰的类型就是枚举类型.形式如下: enum Color { RED, ...

  4. Codeforces Round #333 (Div. 2) B. Approximating a Constant Range

    B. Approximating a Constant Range Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com ...

  5. 项目实践 hrm项目的设计过程

    人事管理系统的设计过程 一.数据库表和持久化类 1.1   进行需求分析,根据功能模块设计数据库表 1.2   设计持久化实体 面向对象分析,即根据系统需求提取出应用中的对象,将这些对象抽象成类,再抽 ...

  6. 使用SQL语句查询Elasticsearch索引数据

    Elasticsearch 的官方查询语言是 Query DSL,存在毕竟有存在的道理,存在即合理.SQL 作为一个数据库查询语言,它语法简洁,书写方便而且大部分服务端程序员都清楚了解和熟知它的写法. ...

  7. 搭建kafka集群

    1:确认zookeeper集群安装正确,防火墙关闭 2:下载kafka安装文件 cd /usr/local/mydown wget http://mirror.bit.edu.cn/apache/ka ...

  8. .Net面试题一

    1.进程和线程的区别是什么? 答:https://www.cnblogs.com/renzhuang/articles/6733461.html2.请列举ASP.Net页面之间传递值的几种方式?列出3 ...

  9. 28-Perl POD 文档

    1.Perl POD 文档Perl 中可以在模块或脚本中嵌入 POD(Plain Old Documentation) 文档.POD 是一种简单而易用的标记型语言(置标语言).POD 文档使用规则: ...

  10. Android获取网络时间的方法

    一.通过免费或者收费的API接口获取 1.免费 QQ:http://cgi.im.qq.com/cgi-bin/cgi_svrtime 淘宝:http://api.m.taobao.com/rest/ ...