JavaScript的学习,就这一篇就OK了!(超详细)

目录

Day27 JavaScript(1)

1、JS的引入方式

2、ECMAScript基本语法

3、ECMAScript 基本数据类型​编辑

3.1 数字类型

3.2 字符串

3.3 布尔值

3.4 空值(Undefined和Null)

3.5 类型转换

3.6 原始值和引用值

4、运算符

5、流程控制语句

5.1 分支结构

5.2 循环语句

6、数组对象

7、Object对象

7.1 object对象的基本操作

7.2 json序列化和反序列化

8、Date对象

9、Math对象

10、Function 对象

10.1 声明函数

10.2 函数调用

10.3 函数参数

10.4 函数返回值

10.5 匿名函数

10.6 函数作用域

10.7 JS的预编译

10.7.1 全局预编译

10.7.2 解释执行代码(直到执行调用函数foo(20)语句)

10.7.3 调用函数foo(20)前发生布局预编译


Day27 JavaScript(1)

1、JS的引入方式

1 直接编写<script>console.log('hello yuan')</script>
2 导入文件<script src="hello.js"></script>

2、ECMAScript基本语法

js是一门弱类型的编程语言,属于基于对象和基于原型的脚本语言.

  • 变量  

格式:// 方式1 先声明再赋值var 变量名;   // 声明的变量如果没有进行赋值,或者没有被定义的变量,值默认是undefined变量名 = 变量值;// 方式2 声明并赋值var 变量名 = 变量值;// 方式3 一行可以声明多个变量.并且可以是不同类型var name="yuan", age=20, job="lecturer";

1、声明变量时 可以不用var. 如果不用var 那么它是全局变量

2、变量命名,首字符只能是字母,下划线,$美元符 三选一,余下的字符可以是下划线、美元符号或任何字母或数字字符且区分大小写

  • 注释

// 单行注释
​/*多行注释*/
  • 语句分隔符

var a = 1   // 分号和换行符作为语句分隔符号
var b = 2;
console.log(a,b)

3、ECMAScript 基本数据类型

3.1 数字类型

JavaScript 没有整型和浮点型,只有一种数字类型,即number类型。

var x = 10;
var y = 3.14;
console.log(x,typeof x);  // 10 "number"
console.log(y,typeof y);  // 3.14 "number"

3.2 字符串

字符串创建(两种方式)

  • 变量 = “字符串”

  • 字串对象名称 = new String (字符串)

var str1="hello world";
var str1= new String("hello word");
// 字符串对象的操作
var str = "hello"; // 这就是字符串对象
console.log(str);// 字符串对象内置属性
// length 计算字符串的长度
console.log( str.length );// 字符串对象内置方法
// toUpperCase();  字母大写转换
// toLowerCase();  字母小写转换console.log( str.toUpperCase() );
console.log( str.toLowerCase() );// indexOf 获取指定字符在字符串中第一次出现的索引位置
// 字符串也有下标,也可以使用中括号来提取字符串的指定字符
console.log(str[1]); // e
console.log( str.indexOf("e") ); // 1// 切片,当前方法支持使用负数代表倒数下标
// slice(开始下标)   从开始位置切到最后
// slice(开始下标,结束下标)  从开始下标切到指定位置之前
var str = "helloworld";
var ret = str.slice(3,6); // 开区间,不包含结束下标的内容
console.log(ret); // low
var ret = str.slice(5);
console.log(ret); // world
var ret = str.slice(2,-1);
console.log(ret); // lloworl
var ret = str.slice(-4,-1);
console.log(ret); // orl
var ret = str.slice(-1,-4);
console.log(ret); // orl// split   正则分割,经常用于把字符串转换成数组
var str = "广东-深圳-南山";
var ret = str.split("-");
console.log( ret );// substr  截取
var str = "hello world";
var ret = str.substr(0,3);
console.log(ret); // hel// trim    移除字符串首尾空白
var password = "    ge llo   ";
var ret = password.trim();
console.log(password.length); // 13
console.log(ret.length);  // 6

3.3 布尔值

1、Boolean类型仅有两个值:true和false,也代表1和0,实际运算中true=1,false=0 2、布尔值也可以看作on/off、yes/no、1/0对应true/false; 3、Boolean值主要用于JavaScript的控制语句

console.log(true);
console.log(false);
console.log(typeof true);
console.log(true === 1);
console.log(true == 1);
console.log(true + 1);
console.log(false + 1);

 

3.4 空值(Undefined和Null)

  • undefined类型

undefined类型只有一个值,即 undefined。

(1)当声明的变量未初始化时,该变量的默认值是 undefined。

(2)当函数无明确返回值时,返回的也是值 undefined;

  • null类型

另一种只有一个值的类型是 null,它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。

尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。

3.5 类型转换

js中,类型转换有2种.一种就是强制转换,一种就是自动转换.

因为js是一门弱类型的脚本语言,所以变量会在运算符的运行要求,有时候根据运算符的要求,进行自动转换的.

  • 强制转换

// 1. 转换数据为数值类型
// parseInt     把数据转换成整数
// parseFloat   把数据转换成小数
// Number       把数据转换成数值
var box1 = "一共100件"; // 转换会失败
var box1 = "100件";     // 转换会成功
var ret = parseInt(box1);
console.log(box1);
console.log(ret);
//
var box2 = "3.14";
console.log(parseFloat(box2) ); // 3.14
//
var box3 = "3.14";   // 使用Number转换的数据里面必须是纯数字!!!!否则都会转换失败
// var box3 = "3.1.4";  // 转换失败!
console.log( Number(box3) );
​
// 对于转换数值,如果转换失败的话,则结果为 NaN ,是 Not a Number ,但是NaN的类型也是number类型
​
// 2. 转换数据为字符串
// 变量.toString()
// String(数据)
var box4 = 3.14;
var ret = box4.toString();
console.log(ret);
//
ret = String(box4);
console.log(ret);
​
// 3. 转换数据成布尔类型
// Boolean()
​
var box5 = "";
console.log( Boolean(box5) ); // false
var box6 = -1;
console.log( Boolean(box6) ); // true
var box7 = 0;
console.log( Boolean(box7) ); // false;
var box8 = "false";
console.log( Boolean(box8) ); // true
var box9 = [];
console.log( Boolean(box9) ); // true
var box10 = {};
console.log( Boolean(box10) ); // true
var box11 = "0";
console.log( Boolean(box11) ); // true
var box12 = null;
console.log( Boolean(box12) ); // false
var box13 = undefined;
console.log( Boolean(box13) ); // false
  • 自动转换

// 所谓的自动转换,其实弱类型中的变量会根据当前代码的需要,进行类型的自动隐式转化
var box1 = 1 + true;
// true 转换成数值,是1, false转换成数值,是0
console.log(box1); // 2
​
var box2 = 1 + "200";
console.log(box2); // 1200 原因是,程序中+的含义有2种,第一: 两边数值相加, 第二: 两边字符串拼接.但是在js中运算符的优先级中, 字符串拼接的优先级要高于数值的加减乘除,所以解析器优先使用了+号作为了字符串的拼接符号了,因为程序就需要+号两边都是字符串才能完成运算操作,因此1变成字符串最终的结果就是 "1" +"200"
​
var box3 = 1 - "200";
console.log(box3); // -199;因为-号中表示的就是左边的数值减去右边的数值,因此程序就会要求"200"是数值,因此内部偷偷的转换了一下

 

3.6 原始值和引用值

根据数据类型不同,有的变量储存在栈中,有的储存在堆中。具体区别如下:

原始变量及他们的值储存在栈中,当把一个原始变量传递给另一个原始变量时,是把一个栈房间的东西复制到另一个栈房间,且这两个原始变量互不影响。

引用值是把 引用变量的名称储存在栈中,但是把其实际对象储存在堆中,且存在一个指针由变量名指向储存在堆中的实际对象,当把引用对象传递给另一个变量时,复制的其实是指向实际对象的指针, 此时 两者指向的 是同一个数据,若通过方法改变其中一个变量的值,则访问另一个变量时,其值也会随之加以改变;但若不是通过方法 而是通过 重新赋值 此时 相当于 重新开了一个房间 该值的原指针改变 ,则另外一个 值不会随他的改变而改变。

// 初始值类型
var a = "yuan";
var b = a;
a = "alvin";
console.log(a);//alvin
console.log(b);//yuan
​
// 对象类型
var arr1=[1,2];
arr2 = arr1;
arr1.push(3);
console.log(arr1)// [1,2,3]
console.log(arr2);//[1,2,3]
​
arr1=[4,5];
console.log(arr1);//[4,5]
console.log(arr2);//[1,2,3]

 

4、运算符

  • 运算符

/*
//算术运算符+   数值相加-   数值相减*   数值相乘/   数值相除%   数值求余**  数值求幂a++ 数值后自增1   a=a+1++a 数值前自增1   a=a+1b-- 数值后自减1   b=b-1--b 数值前自减1   b=b-1//赋值运算符=+=-=*=/=%=**=
​
//比较运算符,比较的结果要么是true, 要么是false>   大于<   小于>=  大于或者等于<=  小于或者等于!=  不等于[计算数值]==  等于[计算]
​!== 不全等[不仅判断数值,还会判断类型是否一致]=== 全等[不仅判断数值,还会判断类型是否一致]
​
//逻辑运算符&&   并且  and    两边的运算结果为true,最终结果才是true||   或者  or     两边的运算结果为false,最终结果才是false!    非    not    运算符的结果如果是true,则最终结果是false ,反之亦然.//逻辑运算符进阶用法:1. 实现短路var a = false || 2      >>> a = 2var a = true && "hehe"  >>>  a = "hehe"2. 快速布尔化[把数据快速转换成布尔类型]var a = 100!!a  >>> true
​
//条件运算符[三目运算符]条件?true:false例如:var age = 12;var ret = age>=18?"成年":"未成年"; // 相当于 python中的"成年" if age >= 18 else "未成年"console.log(ret);*/

 

5、流程控制语句

编程语言的流程控制分为三种:

  • 顺序结构(从上向下顺序执行)

  • 分支结构

  • 循环结构

之前我们学习的方式就是顺序执行,即代码的执行从上到下,一行行分别执行。

例如:

console.log("星期一");
console.log("星期二");
console.log("星期三");

 

5.1 分支结构

  • if 分支语句

if(条件){// 条件为true时,执行的代码}if(条件){// 条件为true时,执行的代码}else{// 条件为false时,执行的代码}if(条件1){// 条件1为true时,执行的代码}else if(条件2){// 条件2为true时,执行的代码}....}else{// 上述条件都不成立的时候,执行的代码}
  • switch语句

switch(条件){case 结果1:满足条件执行的结果是结果1时,执行这里的代码..break;case 结果2:满足条件执行的结果是结果2时,执行这里的代码..break;.....default:条件和上述所有结果都不相等时,则执行这里的代码}

1、switch比if else更为简洁

2、执行效率更高。switch…case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch…case不用像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。

3、到底使用哪一个选择语句,代码环境有关,如果是范围取值,则使用if else语句更为快捷;如果是确定取值,则使用switch是更优方案。

 

5.2 循环语句

  • while循环  

   while(循环的条件){// 循环条件为true的时候,会执行这里的代码}

 

循环案例:

 var count = 0while (count<10){console.log(count);count++;}

 

  • for循环

   // 循环三要素for(1.声明循环的开始; 2.条件; 4. 循环的计数){// 3. 循环条件为true的时候,会执行这里的代码}for(循环的成员下标 in 被循环的数据){// 当被循环的数据一直没有执行到最后下标,都会不断执行这里的代码}   

 

循环案例:

// 方式1
for (var i = 0;i<10;i++){console.log(i)
}
​
// 方式2
var arr = [111,222,333]
for (var i in arr){console.log(i,arr[i])
}

 

  • 退出循环(break和continue)

 for (var i = 0;i<100;i++){if (i===88){continue  // 退出当次循环// break  // 退出当前整个循环}console.log(i)}

 

6、数组对象

  • 创建数组

创建方式1:
var arrname = [元素0,元素1,….];          // var arr=[1,2,3];
​
创建方式2:
var arrname = new Array(元素0,元素1,….); // var test=new Array(100,"a",true);
  • 数组方法

var arr = ["A","B","C","D"];
// 内置属性
console.log( arr.length );
// 获取指定下标的成员
// console.log( arr[3] ); // D
console.log( arr[arr.length-1] ); // 最后一个成员
​
// (1) pop()  出栈,删除最后一个成员作为返回值
var arr = [1,2,3,4,5];
var ret = arr.pop();
console.log(arr); // [1, 2, 3, 4]
console.log(ret); // 5
​
​
// (2) push() 入栈,给数组后面追加成员
var arr = [1,2,3,4,5];
arr.push("a");
console.log(arr); // [1, 2, 3, 4, 5, "a"]
​
​
// (3) shift是将数组的第一个元素删除
var arr = [1,2,3,4,5];
arr.shift()
console.log(arr); // [2, 3, 4, 5]
​
// (4) unshift是将value值插入到数组的开始
var arr = [1,2,3,4,5];
arr.unshift("yuan")
console.log(arr); // ["yuan",1,2, 3, 4, 5]
​
​
// (5) reverse() 反转排列
var arr = [1,2,3,4,5];
arr.reverse();
console.log(arr); // [5, 4, 3, 2, 1]
​
// (6) slice(开始下标,结束下标)  切片,开区间
​
​
// (7) sort() 排序
var arr = [3,4,1,2,5,10];
console.log( arr ); // [3, 4, 1, 2, 5, 10]
arr.sort();
//
// // 这是字符的排序,不是数值的排序
console.log(arr);   //  [1, 10, 2, 3, 4, 5]
​
// 数值升序
var arr = [3,4,1,2,5,10];
arr.sort(function(a,b){return a-b;
});
console.log(arr);  // [1, 2, 3, 4, 5, 10]
​
// 数值降序
var arr = [3,4,1,2,5,10];
arr.sort(function(a,b){return b-a;
});
console.log(arr); // [10, 5, 4, 3, 2, 1]
​
// (8) splice(操作位置的下标,删除操作的成员长度,"替换或者添加的成员1","替换或者添加的成员2")  添加/删除指定的成员   "万能函数"
var arr1 = [1,2,3];
arr1.splice(1,1);
console.log(arr1); // 删除指定的1个成员  [1, 3]
​
var arr2 = ["a","b","c","d"];
arr2.splice(2,0,"w","x","w"); // 添加
console.log(arr2); // ["a", "b", "w", "x", "w", "c", "d"]
​
var arr3 = ["a","b","c"];
arr3.splice(1,1,"w");
console.log(arr3); // ["a", "w", "c"]
​
// (9) concat() 把2个或者多个数组合并
var arr1 = [1,2,3];
var arr2 = [4,5,7];
var ret = arr1.concat(arr2);
console.log( ret );
​
​
// (10) join()  把数组的每一个成员按照指定的符号进行拼接成字符串
var str = "广东-深圳-南山";
var arr = str.split("-");
console.log( arr ); // ["广东", "深圳", "南山"];
​
var arr1 = ["广东", "深圳", "南山"];
var str1 = arr1.join("-");
console.log( str1 ); // 广东-深圳-南山
​
​
// (11) find()  高阶函数, 返回符合条件的第一个成员
var arr = [4,6,5,7];
var func = (num)=>{if(num%2===0){return num;}
};
var ret = arr.find(func);
console.log( ret ); // 4
​
// (12)  filter() 高阶函数, 对数组的每一个成员进行过滤,返回符合条件的结果
var arr = [4,6,5,7];
function func(num){  // 也可以使用匿名函数或者箭头函数if(num%2===0){return num;}
}
var ret = arr.filter(func);  // 所有的函数名都可以作为参数传递到另一个函数中被执行
console.log( ret );
​
// (13) map() 对数组的每一个成员进行处理,返回处理后的每一个成员
var arr = [1,2,3,4,5];
var ret = arr.map((num)=>{return num**3;
});
console.log( ret  ); // [1, 8, 27, 64, 125]
​
// (14) 其它方法
// includes   查询指定数据是否在数组中存在!
// indexOf()  查询指定数据在数组中第一次出现的位置
// isArray()  判断变量的值是否是数组遍历数组var arr = [12,23,34]for (var i in arr){console.log(i,arr[i])}

 

7、Object对象

7.1 object对象的基本操作

Object 的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它们确实是非常理想的选择。 创建 Object 实例的方式有两种。

var person = new Object();
person.name = "alvin";
person.age = 18;

另一种方式是使用对象字面量表示法。对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。下面这个例子就使用了对象字面量语法定义了与前面那个例子中相同的person 对象:

var person = {name : "alvin",age : 18}; 
  • object可以通过. 和 []来访问。

console.log(person["age"]);
console.log(person.age)
  • object可以通过for循环遍历

 for (var attr in person){console.log(attr,person[attr]);}

 

7.2 json序列化和反序列化

JSON:JavaScript 对象表示法(JavaScript Object Notation),是一种轻量级的数据交换格式。易于人阅读和编写。

# json是一种数据格式, 语法一般是{}或者[]包含起来
# 内部成员以英文逗号隔开,最后一个成员不能使用逗号!
# 可以是键值对,也可以是列表成员
# json中的成员如果是键值对,则键名必须是字符串.而json中的字符串必须使用双引号圈起来
# json数据也可以保存到文件中,一般以".json"结尾.
# 前端项目中,一般使用json作为配置文件.{"name": "xiaoming","age":12
}[1,2,3,4]{"name": "xiaoming","age":22,"sex": true,"son": {"name":"xiaohuihui","age": 2},"lve": ["篮球","唱","跳"]
}

js中也支持序列化和反序列化的方法:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<script>// js对象,因为这种声明的对象格式很像json,所以也叫json对象var data = {name: "xiaoming",age: 22,say: function(){alert(123);}};// 把json对象转换成json字符串var ret = JSON.stringify(data);console.log(ret ); // {"name":"xiaoming","age":22}// 把json字符串转换成json对象var str = `{"name":"xiaoming","age":22}`;var ret = JSON.parse(str);console.log(ret);
</script>
</body>
</html>

8、Date对象

  • 创建Date对象

//方法1:不指定参数
var nowd1=new Date();
console.log(nowd1.toLocaleString( ));
//方法2:参数为日期字符串
var d2=new Date("2004/3/20 11:12");
console.log(d2.toLocaleString( ));
var d3=new Date("04/03/20 11:12");
console.log(d3.toLocaleString( ));
//方法3:参数为毫秒数
var d4=new Date(5000);
console.log(d4.toLocaleString( ));
console.log(d4.toUTCString());
//方法4:参数为年月日小时分钟秒毫秒
var d5=new Date(2004,2,20,11,12,0,300);
console.log(d5.toLocaleString( ));//毫秒并不直接显示
  • 获取时间信息

获取日期和时间
getDate()                 获取日
getDay ()                 获取星期
getMonth ()               获取月(0-11)
getFullYear ()            获取完整年份
getYear ()                获取年
getHours ()               获取小时
getMinutes ()             获取分钟
getSeconds ()             获取秒
getMilliseconds ()        获取毫秒
getTime ()                返回累计毫秒数(从1970/1/1午夜)
  • 日期和时间的转换

日期和时间的转换:
// 返回国际标准时间字符串
toUTCString()
// 返回本地格式时间字符串
toLocalString()
// 返回累计毫秒数(从1970/1/1午夜到本地时间)
Date.parse(x)
// 返回累计毫秒数(从1970/1/1午夜到国际时间)
Date.UTC(x)

练习:以2021年03月2日 14:1:43 星期二格式化输出当前时间

function getCurrentDate(){//1. 创建Date对象var date = new Date(); //没有填入任何参数那么就是当前时间//2. 获得当前年份var year = date.getFullYear();//3. 获得当前月份 js中月份是从0到11.var month = date.getMonth()+1;//4. 获得当前日var day = date.getDate();//5. 获得当前小时var hour = date.getHours();//6. 获得当前分钟var min = date.getMinutes();//7. 获得当前秒var sec = date.getSeconds();//8. 获得当前星期var week = date.getDay(); //没有getWeek// 2014年06月18日 15:40:30 星期三return year+"年"+changeNum(month)+"月"+day+"日 "+hour+":"+min+":"+sec+" "+parseWeek(week);}
​
//解决 自动补齐成两位数字的方法
function changeNum(num){if(num < 10){return "0"+num;}else{return num;}
}
//将数字 0~6 转换成 星期日到星期六
function parseWeek(week){var arr = ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"];//             0      1      2      3 .............return arr[week];
}
​
console.log(getCurrentDate());

9、Math对象

 //  Number对象的内置方法//  toFixed(x) 保留小数位var num = 100.3;var ret = num.toFixed(2);console.log(num);  // 100.3console.log(ret);  // 100.30
​
// Math对象的内置方法
// abs(x)  返回数值的绝对值
// var num = -10;
console.log( Math.abs(num) ); // 10
​
// ceil(x)  向上取整
var num = 10.3;
console.log( Math.ceil(num) ); // 11
​
// floor(x) 向下取整
var num = 10.3;
console.log( Math.floor(num) ); // 10
​
// max(x,y,z,...,n)
console.log( Math.max(3,56,3) ); // 56
// min(x,y,z,...,n)
​
// pow(x,y)
console.log(Math.pow(3, 2)); // 相等于 3**2
console.log( 3**2 ); // 使用这个,上面废弃
​
// random()  生成0-1随机数
console.log( Math.random() );
​
// 生成0-10之间的数值
console.log( Math.random() * 10 );
​
// round(x) 四舍五入
// 生成0-10之间的整数
console.log( Math.round( Math.random() * 10 ) );
  • 练习:获取1-100的随机整数,包括1和100

var num=Math.random();
num=num*100;
num=Math.round(num);
console.log(num)

 

10、Function 对象

函数在程序中代表的就是一段具有功能性的代码,可以让我们的程序编程更加具有结构性和提升程序的复用性,也能让代码变得更加灵活强大

10.1 声明函数

// 函数的定义方式1
function 函数名 (参数){函数体;return 返回值;
}
功能说明:可以使用变量、常量或表达式作为函数调用的参数函数由关键字function定义函数名的定义规则与标识符一致,大小写是敏感的返回值必须使用return//  函数的定义方式2用 Function 类直接创建函数的语法如下:
var 函数名 = new Function("参数1","参数n","function_body");虽然由于字符串的关系,第二种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。    

10.2 函数调用

    //f(); --->OKfunction f(){console.log("hello")}f() //----->OK

不同于python,js代码在运行时,会分为两大部分———预编译 和 执行阶段。

  • 预编译:会先检测代码的语法错误,进行变量、函数的声明。

  • 执行阶段:变量的赋值、函数的调用等,都属于执行阶段。

 

10.3 函数参数

(1) 参数基本使用

// 位置参数
function add(a,b){console.log(a);console.log(b);
}
add(1,2)
add(1,2,3)
add(1)// 默认参数
function stu_info(name,gender="male"){console.log("姓名:"+name+" 性别:"+gender)
}stu_info("yuan")

(2)函数中的arguments对象

function add(a,b){
​console.log(a+b);//3console.log(arguments.length);//2console.log(arguments);//[1,2]
​}
add(1,2)
​
// arguments的应用1 
function add2(){var result=0;for (var num in arguments){result+=arguments[num]}console.log(result)
​
}
​
add2(1,2,3,4,5)
​
// arguments的应用2
​
function f(a,b,c){if (arguments.length!=3){throw new Error("function f called with "+arguments.length+" arguments,but it just need 3 arguments")}else {alert("success!")}
}
​
f(1,2,3,4,5)

10.4 函数返回值

在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。

function add(x,y) {return x+y}
​
var ret = add(2,5);
console.log(ret)

1、在函数体内可以包含多条 return 语句,但是仅能执行一条 return 语句

2、函数的参数没有限制,但是返回值只能是一个;如果要输出多个值,可以通过数组或对象进行设计。

 

10.5 匿名函数

匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。

      // 匿名函数赋值变量var foo = function () {console.log("这是一个匿名函数!")};
​// 匿名函数的自执行(function (x,y) {console.log(x+y);})(2,3)
​
​// 匿名函数作为一个高阶函数使用function bar() {
​return function () {console.log("inner函数!")}}
​bar()()

使用匿名函数表达式时,函数的调用语句,必须放在函数声明语句之后!

10.6 函数作用域

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理。

任何程序设计语言都有作用域的概念,简单的说,作用域就是变量可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

// 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
// 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉

首先熟悉下var

    var name = "yuan"; // 声明一个全局变量 name并赋值”yuan“name = "张三";  // 对已经存在的变量name重新赋值 ”张三“console.log(name);
​age = 18   // 之前不存在age变量,这里等同于var age = 19 即声明全局变量age并赋值为18
​var  gender = "male"var  gender = "female" // 原内存释放与新内存开辟,指针指向新开辟的内存console.log(gender)

作用域案例:

 var num = 10; // 在函数外部声明的变量, 全局变量function func(){// num = 20; // 函数内部直接使用变量,则默认调用了全局的变量,//var num = 20; // 函数内部使用var 或者 let声明的变量则是局部变量// 函数内部直接使用变量,则默认调用了全局的变量,// 使用变量的时候,解释器会在当前花括号范围值搜索是否有关键字var 或者 let 声明了变量,如果没有,则一层一层往外查找最近的声明// 如果最终查找不到,则直接报错! 变量名 is not define!console.log("函数内部num:",num)}
func();
console.log("全局num:",num);

 

10.7 JS的预编译

js运行三个阶段:

  1. 语法分析

  2. 预编译

  3. 解释执行

语法分析就是JS引擎去检查你的代码是否有语法错误,解释执行就是执行你的代码。最重要最需要理解的就是第二个环节预编译,简单理解就是在内存中开辟一些空间,存放一些变量与函数 。

预编译可分为全局预编译和局部预编译。

  1. 在js脚本加载之后,会先通篇检查是否存在低级错误;

  2. 在语法检测完之后,便进行全局预编译;

  3. 在全局预编译之后,就解释一行,执行一行;

  4. 当执行到函数调用那一行前一刻,会先进行函数预编译,再往下执行。

全局预编译的3个步骤:

  1. 创建GO对象(Global Object)全局对象,即window对象。

  2. 找变量声明,将变量名作为GO属性名,值为undefined

  3. 查找函数声明,作为GO属性,值赋予函数体

局部预编译的4个步骤:

  1. 创建AO对象(Activation Object)执行期上下文。

  2. 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined

  3. 将实参值和形参统一。

  4. 在函数体里面找函数声明,值赋予函数体。

GO对象是全局预编译,所以它优先于AO对象所创建和执行

案例分析:

 <script>var a = 10;console.log(a);
​function foo(a) {console.log(a);var a = 100;console.log(a);function a() {}console.log(a);var b = function(){};console.log(b);function d() {}}var c = function (){console.log("匿名函数C");};console.log(c);foo(20);
​</script>
10.7.1 全局预编译
    GO/window = {a: undefined,c: undefined,foo: function(a) {console.log(a);var a = 123;console.log(a);function a() {}console.log(a);var b = function() {}console.log(b);function d() {}}}

 

10.7.2 解释执行代码(直到执行调用函数foo(20)语句)
GO/window = {a: 10,c: function (){console.log("I at C function");}test: function(a) {console.log(a);var a = 123;console.log(a);function a() {}console.log(a);var b = function() {}console.log(b);function d() {}}}

 

10.7.3 调用函数foo(20)前发生布局预编译
// 局部预编译前两步:
AO = {a:undefined,b:undefined,}
​
// 局部预编译第三步:
AO = {a:20,b:undefined,}
// 局部预编译第四步:
AO = {a:function a() {},b:undefinedd:function d() {}}

预编译总结:

  1. 函数声明整体提升-(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)

  2. 变量 声明提升-(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined)

面试题:

var num3 = 10;
function func3(){console.log(num3); var num3 = 20;       
}
func3();
console.log(num3); 
​
​/*
​// 全局编译
​GO{num3:undefined,func3: function (){console.log(num3);var num3 = 20;}
​// 全局执行var num3 = 10;GO{num3:10,func3: function (){console.log(num3);var num3 = 20;}
​
​// 局部编译func3.AO{num3:undefined,}
​
​// 局部执行
​func3.AO{num3:20,}
​// 全局执行
​GO.num3 = 10}
​
*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/151431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能

近年来&#xff0c;日志管理平台越来越流行。使用日志管理平台可以实时地、统一地、方便地管理和查看日志&#xff0c;挖掘日志数据价值&#xff0c;驱动运维、运营&#xff0c;提升服务管理效率。 方案架构 Beats 是轻量级采集器&#xff0c;包括 Filebeat、Metricbeat 等。E…

给大伙讲个笑话:阿里云服务器开了安全组防火墙还是无法访问到服务

铺垫&#xff1a; 某天我在阿里云上买了一个服务器&#xff0c;买完我就通过MobaXterm进行了ssh&#xff08;这个软件是会保存登录信息的&#xff09; 故事开始&#xff1a; 过了n天之后我想用这个服务器来部署流媒体服务&#xff0c;咔咔两下就部署好了流媒体服务器&#x…

基于SSM的供电公司安全生产考试系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

云桌面 node_modules 切换艰辛历程记录 rebuild失败记录

拿到node_modules后更换 执行npm rebuild 重新构建 报错 node版本不一致 nvm切换 版本 不成功 换个窗口又变回原来版本号了 设置默认版本 nvm alias default 14.16.1 发现下面还有一个stable的还指向原来版本 nvm alias stable 14.16.1 rebuild 还是失败 逐个rebuild 每个依赖单…

2.FastRunner定时任务Celery+RabbitMQ

注意&#xff1a;celery版本和Python冲突问题 不能用高版本Python 用3.5以下&#xff0c;因为项目的celery用的django-celery 3.2.2 python3.7 async关键字 冲突版本 celery3.x方案一&#xff1a; celery3.xpython3.6方案二 &#xff1a; celery4.xpython3.7 解决celery执…

Python---PyCharm调试技巧--Step over(F8)、Step into(F7)

Step over&#xff08;F8&#xff09;&#xff1a;代码一步一步向下执行&#xff0c;但是遇到了函数以后&#xff0c;不进入函数体内部&#xff0c;直接返回函数的最终的执行结果。------------遇到函数跳过&#xff0c;直接执行最后的结果。 Step into&#xff08;F7&#xf…

UDP网络套接字编程

先来说说数据在网络上的传输过程吧&#xff0c;我们知道系统其实终究是根据冯诺依曼来构成的&#xff0c;而网络数据是怎么发的呢&#xff1f; 其实很简单&#xff0c;网络有五层。如下&#xff1a; 如上图&#xff0c;我们知道的是&#xff0c;每层对应的操作系统中的那些地方…

ESP32-BLE基础知识

一、存储模式 两种存储模式&#xff1a; 大端存储&#xff1a;低地址存高字节&#xff0c;如将0x1234存成[0x12,0x34]。小端存储&#xff1a;低地址存低字节&#xff0c;如将0x1234存成[0x34,0x12]。 一般来说&#xff0c;我们看到的一些字符串形式的数字都是大端存储形式&a…

基于SSM的高校毕业选题管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

flink源码分析之功能组件(一)-metrics

简介 本系列是flink源码分析的第二个系列,上一个《flink源码分析之集群与资源》分析集群与资源,本系列分析功能组件,kubeclient,rpc,心跳,高可用,slotpool,rest,metric,future。其中kubeclient上一个系列介绍过,本系列不在介绍。 本文介绍flink metrics组件,metric…

OceanBase 4.2.1 LTS 发版 | 一体化数据库首个长期支持版本

在刚刚结束的年度发布会上&#xff0c;OceanBase 沿着“一体化”产品战略思路&#xff0c;发布了一体化数据库的首个长期支持版本 4.2.1 LTS。作为 4.0 系列的第一个 LTS 版本&#xff0c;该版本的定位是支撑客户关键业务稳定长久运行&#xff0c;我们非常认真的打磨了这个版本…

Java学习之路 —— 多线程

文章目录 1. 线程创建方式1.1 继承Thread1.2 声明一个实现Runnable接口的类1.3 利用Callable接口、FutureTask类来实现 2. 线程同步2.1 同步代码块2.2 同步方法2.3 Lock锁 3. 线程同步4. 线程池 1. 线程创建方式 1.1 继承Thread 定义子类&#xff0c;继承Thread&#xff0c;创…

Android描边外框stroke边线、rotate旋转、circle圆形图的简洁通用方案,基于Glide与ShapeableImageView,Kotlin

Android描边外框stroke边线、rotate旋转、circle圆形图的简洁通用方案&#xff0c;基于Glide与ShapeableImageView&#xff0c;Kotlin 利用ShapeableImageView专门处理圆形和外框边线的特性&#xff0c;通过Glide加载图片装载到ShapeableImageView。注意&#xff0c;因为要描边…

Docker 容器中的网络优化与 DNS 缓存清理

在使用Docker 18.03.1-ce版本在Ubuntu 18.04 LTS上运行多个Docker容器时&#xff0c;我发现当使用requests库发送请求到某个主机名时&#xff0c;响应速度非常慢。在本例中&#xff0c;每个容器都有自己的CherryPy服务器&#xff0c;并通过requests.get(http://main:8083)或req…

Nginx 413 Request Entity Too Large

当出现上图时候 更改nginx config 文件 在http{}或者server{}或者location{}中增加client_max_body_size 100m; 然后重启nginx 服务就好了

轻松搭建短域名短链接服务系统,可选权限认证,并自动生成证书认证把nginx的http访问转换为https加密访问,完整步骤和代码

轻松搭建短域名短链接服务系统&#xff0c;可选权限认证&#xff0c;并自动生成证书认证把nginx的http访问转换为https加密访问&#xff0c;完整步骤和代码。 在互联网信息爆炸的时代&#xff0c;网址复杂而冗长&#xff0c;很难在口头告知他人&#xff0c;也难以分享到社交媒体…

11 月 18 日 ROS 学习笔记——可视化和调试工具

文章目录 前言一、调试 ROS 节点1. gdb 调试器2. 在 ROS 节点启动时调用 gdb 调试器3. 在 ROS 节点启动时调用 valgrind 分析节点4. 设置 ROS 节点 core 文件转储5. 日志消息1). 输出日志消息2). 设置调试消息级别 二、检测系统状态1. rqt_graph2. 可视化坐标变换3. 保存与回放…

trzsz支持文件拖动到终端进行上传,类似lrzsz

考虑到 LapTop -> Host 1 -> Host 2 -> Docker -> TMUX&#xff0c;使用scp或sftp命令不方便&#xff1b;使用rz和sz命令就会方便很多&#xff0c;但是却又与 TMUX 不兼容&#xff08;备注&#xff1a;Tmux是一个终端复用工具&#xff0c;允许用户在一个终端窗口中…

初学UE5 C++②

目录 导入csv表格数据 创建、实例化、结构体 GameInstance Actor camera 绑定滚轮控制摇臂移动 碰撞绑定 角色碰撞设定 按钮 UI显示 单播代理 多播和动态多播 写一个接口 其他 NewObject 和 CreateDefaultSubobject区别 导入csv表格数据 创建一个object的C类 …

设计模式-责任链-笔记

动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;一个请求可能被多个对象处理&#xff0c;但是每个请求在运行时只能有个接受者&#xff0c;如果显示指定&#xff0c;将必不可少地带来请求者与接受者的紧耦合。 如何使请求的发送者不需要指定具体的接受…