JavaScript 函数声明和变量声明
声明语句:声明语句是用来声明或定义标识符(变量和函数名)并给其赋值。
1:var 变量声明(5.3.1节):
var语句用来声明一个或多个变量:var name_1 = [= value_1] [ ,..., name_n [= value_n]]
var i;
var j = 0;
var x=1, y=2;
var pi = 3.14,
f = function(x) {return x*x},
k = f(x);
2:遗漏声明(3.9节)
读取一个没有声明的变量的值:JavaScript会报错。
给一个未声明的变量赋值,(在非严格模式中)JavaScript实际上是给全局对象创建一个同名属性,这看起来像是JavaScript自动声明了一个全局变量。
x // => Uncaught ReferenceError: x is not defined *读取一个未声明的变量会报错
x=1 // 给一个未声明的变量赋值,等于创建一个全局变量
x // => 1。
3:重复声明(3.9节)
使用var语句重复声明变量是合法且无害的。
var v1 = 1
var v1 = 2 // 重复声明带有初始化器,这条语句就像是简单的赋值语句
v1 // => 2var v2 = 1;
var v2 // 重复声明语句不带初始化器,那就什么也不发生
v2 // y的结果是1
4:严格模式:"use strict"语句(5.7.3节)
在JavaScript设计之初留下了许多被人诟病的问题,比如变量在声明之前就可以访问,比如给未声明的变量赋值,则这个变量会被定义为一个全局变量,这样会扰乱全局作用域的属性。
ECMAScript5定义了严格模式,严格模式是该语言的一个受限制的子集,它修正了语言的严重缺陷,并提供健壮的差错功能和增强的安全机制。
在严格模式中,给未声明的变量赋值会报错,在变量定义的代码之前读取该变量也会报错。
5:function:函数声明(5.3.2节)
关键字function用来定义函数。
- 函数声明语句
function f(x) { return x + 1; }
- 函数定义表达式
var f = function(x) { return x + 1; }
5.1:函数调用表达式(invocation expression)(4.5节)
函数调用表达式:以一个函数表达式开始,函数表达式后跟随一对圆括号,括号内是一个以逗号分割开的参数列表。
f()
f(0)
Math.max(x,y,z)
5.2:函数声明表达式和函数声明语句(4.3节、5.1节)
函数定义表达式:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/function
function [name]([param_1[, param_2[, ..., param_N]]]) {
[statements]
};
函数声明语句:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/function
function name([param_1,[, param_2,[..., param_N]]]) {
[statements]
}
函数声明语句和函数表达式语句几乎没有区别,唯一的区别是函数定义表达式的函数名(name)是可选的,JavaScript预编译把一段函数定义代码编译成表达式还是语句,主要看这段code出现的位置。
表达式(expression):JavaScript解释器会将表达式计算(evaluate)出一个结果,如果没有赋值语句,则这个结果不会产生任何副作用。复杂的表达式由简单的表达式组合而成。语句(statement):语句用来执行使某件事情发生,是会产生“副作用”的表达式。
语句:直接使用符合函数声明语句的格式定义一个函数,则JS将函数编译为为函数声明语句。
function f1(x) { return x*x; } // 这条语句会产生一个副作用,就是定义了一个name为f1的函数。
f1; // 输出f1,可以看到函数的值。(在JS中,函数也是一个值)
f1(3); // =>9 当然,你可以用函数调用表达式调用这个函数,输出结果是9
表达式:
- 出现在等号左边的函数定义,JavaScript通常会编译为函数定义表达式。
var f2 = function(x){ return x*x; } // 这个函数定义会被编译为函数定义表达式,计算出的结果再赋值到变量f2。
f2; // 输出f2,可以看到函数的值。(在JS中,函数也是一个值)
- 出现在括号里的函数定义,JavaScript通常会编译为函数定义表达式:
[1,2,3].map(function(x){ return x*x }) // 定义一个匿名函数
(function(){return 1}()) // 定义一个立即调用函数
(function(){return 1})() // 同上
这也就是为什么立即调用函数一定要用括号括起来的原因,如果没有括号,js预编译会把它当作一个函数声明语句
- 出现在方括号里的函数定义,JavaScript通常会编译为函数定义表达式:
[function(){return 1;}]
- 箭头函数表达式:箭头函数表达式的语法比函数表达式更短。
表达式计算出一个值,在JavaScript中,函数就是一个值,可以被赋值可以被传递,但表达式不会对程序产生副作用
var f4 = function ff(x){ return x*x; }; ff; // =>undefined *因为表达式不产生副作用,没有名为ff函数,如果调用ff(),会报错
(function ff(){return 1})(); ff; // 同上
[function ff(){return 1;}]; ff; // 同上
5.3:避免js引起错误编译, ( [ + - / 前加分号
上面有4种情况:等于号、圆括号、方括号,箭头函数会被认为是表达式。
一条语句如果以这些符号开头,那么js编译器会把他们当作表达式来解析,那么就会产生问题,因为JS一条句子结束可以不加分号,而这里表达式并不是一句语句,所以这个表达式会和前面(没有分号的句子)表达式合并成一条语句。
比如在任意一条语句后面定义匿名函数,都会报错。
var a = 1
(function(){ console.log('hello world') })()
// => Error: 1 is not a function
这是因为匿名函数这里被当作表达式解析,但表达式不是一条语句,所以会和前面的内容合并成一条语句。如果以 [ 也同理。当然我们不会以等于号开头以及箭头函数开头。所以要格外注意以 ( 和[ 开头的句子。解决办法就是在 ( 前面加一上分号。当然,很多都会每一行结尾加分号,这也能避免这种麻烦。
var a = 1
;(function(){ console.log('hello world') })()
类似的情况还有加号+、减号-、正则的起始符/,所以遇到 ( [ + - / 这5个符号开头的句子,要注意让编译器知道这些表达式不属于前面的语句。
也就是如果你是一个不喜欢加分号的程序员,那就要在这5个符号开头的句子前加上分号,或者避免以这5个符号开头。
6:声明提前(hoisting)(3.10.1节)
JavaScript引擎在“预编译”会把var声明语句会和函数声明语句提前至函数顶部,这就意味着整个作用域内都可以该变量。但var声明语句的初始化代码不会被提升到函数顶部,所以在初始化代码之前访问变量,则变量的值为undefined,声明代码之前给变量赋值,则是一条正常的赋值语句。
console.log(v3) // 声明被提前,但在初始化之前访问,不会报错,结果未undefined
var v3 = 1 // “预编译”已经将声明提前,“解释器”运行到此是初始化变量
console.log(v3) // 在初始化之后访问v3,结果是
在变量声明代码之前给变量赋值,是一条正常的赋值语句,并不是遗漏声明,因为代码声明已经被提至函数顶部。
function f(){
a = 1 // 预编译在代码解释之前完成,当解释器解释到这条赋值语句的时候,预编译已经声明变量a,所以这是一条正常的赋值语句
var a // 声明是预编译完成的,并不是js解释器完成的
}f();
a // => a is not defined 因为a=1并不是遗漏声明,所以没有创建全局变量
注意:在声明变量的代码之前调用变量是没有任何问题,而给遗漏声明的变量赋值JS会自动创建一个全局变量,但是访问为声明的变量会报错。console.log(v4); // Uncaught ReferenceError: v4 is not defined
作用域链上找不到对象时会报错,原型链上找不到属性是返回undfined,不报错。
f1() // 函数声明也被提前,在定义函数之前就可以调用函数f1
function f1(){return 1;}
function f2(){return ff; function ff(){return 100;}}
f2()() // ff的声明被提前,所以返回的ff是一个函数对象
函数声明语句会提前,而函数定义语句不会提前。这就比较有趣了,var变量声明会被提前,但函数定义要到初始化表达式的时候,才会定义。
f3 // 和函数声明语句截然相反,函数表达式的定义并没有提升,f3的值是undefined,
var f3 = function() {return 1;} // 用函数定义表达式定义一个函数。
function f4(){return ff; var ff = function (){return 100;}}
f4() // ff声明提前,但表达式定义没有提前,所以返回的ff是一个undefined
@@@在ES2015之前,申明变量都用var,var只有函数作用域和局部作用域,没有块作用域,在ES2015开始,有let和const
JavaScript 函数声明和变量声明的更多相关文章
- javascript中函数声明、变量声明以及变量赋值之间的关系与影响
javascript中函数声明.变量声明以及变量赋值之间的关系与影响 函数声明.变量声明以及变量赋值之间有以下几点共识: 1.所有的全局变量都是window的属性 2.函数声明被提升到范围作用域的顶端 ...
- (转载)javascript函数作用域和提前声明
http://www.cnblogs.com/ArthurPatten/p/3274080.html 一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们 ...
- javascript函数作用域和提前声明
一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的,但是javascript没有块级作用域.javascript使用函数作用域,即 ...
- JavaScript 函数的两种声明方式
1.函数声明的方式 JavaScript声明函数有两种选择:函数声明法,表达式定义法. 函数声明法 function sum (num1 ,num2){ return num1+num2 } 表达式定 ...
- Javascript中的循环变量声明,到底应该放在哪儿?
相信很多Javascript开发者都在声明循环变量时犹豫过var i到底应该放在哪里:放在不同的位置会对程序的运行产生怎样的影响?哪一种方式符合Javascript的语言规范?哪一种方式和ecma标准 ...
- JavaScript变量声明与变量声明提前
JavaScript变量声明 JavaScript中存储数据的容器称为变量.用关键字和标识符创建新变量的语句,称为变量声明.可以通过关键字var进行变量声明,在ES6中增加了let.const关键字声 ...
- [JavaScript]JS中的变量声明与有效域
1.变量声明 var a = 1; //使用var声明变量 b = 1; //不使用var 第一种情况,在当前域中声明一个名为a的变量,如果实在方法内则为局部变量,若在最外层声明则a为全局变量. 第二 ...
- javascript 函数的几种声明函数以及应用环境
本页只列出常用的几种方式,当然还有比如new Function()以及下面三种的组合. 1.函数式声明 例子:function sum(a,b){ return a+b; }; 2.函数表达式声明(匿 ...
- 浅谈javascript函数,变量声明及作用域
javascript函数跟变量的声明.作用域这些概念网上都已经讲烂了. 这里写个博客,也相当于做个笔记. 变量声明 首先看个例子: var globalVar = "gv"; fu ...
随机推荐
- 用C++实现的数独解题程序 SudokuSolver 2.2 及实例分析
SudokuSolver 2.2 程序实现 根据 用C++实现的数独解题程序 SudokuSolver 2.1 及实例分析 里分析,对 2.1 版做了一些改进和尝试. CQuizDealer 类声明部 ...
- 乘风破浪,遇见最美Windows 11之新微软商店(Microsoft Store)生态 - 安卓(Android™)开发体验指南
什么是Windows 11的安卓(Android)应用 2021年6月25日,微软召开线上发布会,对外宣告下一代Windows操作系统Windows 11,Windows 11为用户重新打造的Micr ...
- 网络通信IO的演变过程(一)(一个门外汉的理解)
以前从来不懂IO的底层,只知道一个大概,就是输入输出的管道怼到一起,然后就可以传输数据了. 最近看了周志垒老师的公开课后,醍醐灌顶. 所以做一个简单的记录. 0 计算机组成原理相关 0.1. 计算机的 ...
- [敏捷软工团队博客]Beta设计和计划
项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta设计和计划 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Beta ...
- [no code][scrum meeting] Alpha 13
项目 内容 会议时间 2020-04-21 会议主题 OCR技术对接会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalo ...
- Spring Security Jwt Token 自动刷新
token的自动刷新 一.功能需求 二.功能分析 1.token 的生成 2.token 的自动延长 3.系统资源的保护 4.用户如何传递 token 三.实现思路 1.生成 token 和 refr ...
- Vue | uni-app 中使用websocket
@ 目录 首先在根目录下新建一个store文件夹,并新建一个websocket.js文件,代码如下: import Vue from 'vue' import Vuex from 'vuex' Vue ...
- 转载: XILINX GT的基本概念
https://zhuanlan.zhihu.com/p/46052855 本来写了一篇关于高速收发器的初步调试方案的介绍,给出一些遇到问题时初步的调试建议.但是发现其中涉及到很多概念.逐一解释会导致 ...
- 第01课 OpenGL窗口(3)
接下来的代码段创建我们的OpenGL窗口.我花了很多时间来做决定是否创建固定的全屏模式这样不需要许多额外的代码,还是创建一个容易定制的友好的窗口但需要更多的代码.当然最后我选择了后者.我经常在EMai ...
- (一)FastDFS 高可用集群架构学习---简介
1.什么是FastDFS FastDFS 是余庆老师用c语言编写的一筐开源的分布式文件系统,充分考虑了冗余备份,负载均衡,线性扩容等机制,并注重高可用.高性能等指标,使用FastDFS可以很容易搭建一 ...