1.JavaScript语言的执行流程
编译阶段:构建执行函数;执行阶段:代码依次执行
2.代码块:{ }
3.变量声明方式var
有声明提升,允许重复声明,声明函数级作用域
访问:声明后访问都是正常的,在声明之前访问值为undefined
(对于变量来说,变量允许使用的范围被称为作用域)
<script>//for(表达式1;表达式2;表达式3)//表达式1 执行1次//表达式2 执行n+1次//表达式3 执行n次for(var i = 0;i<10;i++){console.log(i);}debugger;//此处可以访问到i变量,可以证明var声明的变量是函数级作用域console.log('循环后输出i变量的值',i)//10</script>
4. ES6新增的变量声明方式let
没有声明提升,不允许重复声明但允许重新赋值,声明块及作用域
访问:声明前不允许访问
(变量访问时,如果当前作用域不存在,则沿作用域向上级作用域查找,找到即返回,直到全局作用域未找到返回undefined)
<script>//console.log('let声明变量a:',a);//Cannot access 'a' before initializationlet a = 10;// let a = 100;// Identifier 'a' has already been declareda = 100; //允许重新赋值{let a = 100;//此处通过let声明变量a,作用域仅限于当前代码块内部,所以let声明的变量是块及作用域console.log('代码块中let a=',a);//代码块中let a= 100debugger;//用于调试JS代码}console.log('a',a);//a 100</script>
<script>for(let i = 0;i<10;i++){console.log(i);//1,2,3,4,5,6,7,8,9}console.log('循环后输出i变量的值',i);//此处访问的是全局变量i,所以报错</script>
5.变量声明方式const
声明前必须复制,不允许重复赋值,块级作用域,不存在变量提升
暂时性死区:声明(编译阶段)到赋值(执行阶段)之间的区域被称为暂时性死区
<script>/*** - JS中的数据类型* - 数值类型* - Number,String,Boolean,Null,Undefined* - 引用类型* - Array,Object* 对于引用类型来说,通过地址修改属性的值,不是重新赋值* const修饰的是变量的特征,而不是对象的特征*///声明时必须赋值const a = 10;{const a = 100;console.log(a);//100}//a = 200;//报错,常量不允许重新赋值console.log(a);//10//对于引用类型来说,变量中存储的地址改变了,才是重新赋值const obj = {name:'张三',age:18}//通过obj修改了name属性的值obj.name = '李四';//obj = [4,5,6];//报错,因为变量的值不能改变console.log(obj);//age:18,name:"李四"</script>
6.函数的声明方式
6.1new Function()构造函数形式
// new Function()构造函数形式let fn1 = new Function('return 1');console.log(fn1.toString());//function anonymous() {return 1};
6.2function函数声明
声明前置(提升),可以在声明前调用,必须拥有函数名,并且函数名符合标识规范
<script>//function函数声明fn2();//输出fn2 executedfunction fn2(){console.log('fn2 executed');return 2;}fn2();//输出fn2 executed</script>
6.3函数表达式let fn() = function(){}
<script>fn3();//报错,var fn3相当于变量提升,值为undefind,不是函数不可以调用var fn3 = function(){console.log('fn3 executed');return 3;}fn3();//fn3 executed</script>
6.4立即执行函数表达式(function() {})()
function前面一定要加(),因为function是关键字,function如果作为一行的第一个字符,则被认为函数声明结构
<script>//立即执行函数表达式,是特殊的函数表达式形式,声明后立即调用,特性与函数表达式方式相同//此处只需要证明function不是第一个字符(function(){console.log('fn4 executed');})();</script>
7.函数参数
函数定义时被称为形参,函数调用时参数被称为实参;实参的数量=形参的数量时依次赋值;实参的数量>形参的数量时依次赋值多余的实参被忽略;实参的数量<形参的数量时依次赋值未被赋值的形参为undefined
<script>//形参默认值function fn(a,b,c,d=500){console.log(a,b,c,d);}fn(1,2,3,4);//输出1,2,3,4//当实参的值为undefined时执行默认值fn(1,2,3,undefined,null);//输出1,2,3,500</script>
8.剩余参数...args在函数定义时,被称为剩余函数
函数声明时使用;ES6新特性,用于替换arguments对象
特征:只能有一个剩余函数;必须是最后一个参数; 是数组,可以使用数组的方法
<script>function add(a,b,...args){console.log(a,b,args);}add(1,2,3,4,5,6,7,8,9,10);</script>
<script>function add(a,b,...args){console.log(a,b,...args);}add(1,2,3,4,5,6,7,8,9,10);//输出1 2 3 4 5 6 7 8 9 10</script>
9.延展操作符...变量
可以展开的是可迭代对象(ES6中新增的内容),延展操作符可以展开变量的内容
延展操作符与剩余参数二者格式相同,都是...变量;在函数调用时使用,是延展操作符 ,将可迭代对象展开
<script>function add(a,b){console.log(a,b);}add(1,2);//输出1,2add([3,4]);//输出[3, 4] undefined//赋值给a变量,b变量没有赋值let arr = [3,4];add(...arr);//输出3,4let str = 'xy';add(...str);//x ylet obj = {name:'zhangsan',age:18}//add(...obj);//报错//默认情况下,对象不能展开let array = ['a','b','c'];console.log(array);//['a', 'b', 'c']console.log(...array);//a b c//可迭代对象中每一个项作为参数传递给函数console.log('a','b','c');//a b c//...array效果相同</script>
10.严格模式
就是在代码的头部加上use strict
在严格模式下,函数的arguments和当前函数定义的形参是没有映射关系,并且禁用arguments.callee和arguments.callee.caller(caller是function的属性)
arguments变成类数组对象 (特征像数组,拥有length属性,本质是一个对象)
<script>function fn3(a,b,c){"use strict";//严格模式的开关,如果解释器识别则进入严格模式console.log(arguments);console.log(a,b,c);}fn3(4,5,6);</script>
函数的形参拥有默认值函数内部自动进入严格模式
<script>function fn3(a,b,c=100){console.log(arguments);console.log(a,b,c);}fn3(4,5,6);</script>
两种代码输出结果一致