i++
}
console.log(sum) // 5050
补充:i++ 和 ++i 的理解
i++ 是自增运算符,表示把当前的变量自增一个单位。(先运算、后自增)
++i 是先自增一个单位,然后在运算。(先自增、后运算)
不论是 i++ 还是 ++i ,只要执行完毕,i的值都是自增。
for循环和while循环语法
for循环:
for(语句1; 语句2; 语句3){
被执行的代码块
}
语句1:在循环(代码块)开始前执行
语句2:定于运行循环(代码块)的条件
语句3:在循环(代码块)已被执行之后执行
while循环:会在指定条件为真时循环执行代码块
while(条件){
需要执行的代码
}
5、对象内容的遍历
使用typeof来查看JavaScript变量的数据类型
现在需要判断一个对象中哪些是属性哪些是函数,使用typeof关键字
案例:
var n1 = 13;
var s1 = “abc”
function fun() {
}
console.log(typeof(n1)) // number
console.log(typeof(s1)) // string
console.log(typeof(fun)) // function
那么,该如何遍历一个对象呢?
var person = {
name : “张三”,
age : 18,
eat : function () {
console.log(“爱吃KFC”)
}
}
for (var p in person){
console.log(p,“值:”+person[p])
}
小结:遍历对象时使用中括号的方式,因为不知道对象中的变量究竟是属性还是方法,所以使用中括号更加灵活。
6、JavaScript运算符
运算符:加、减、乘、除、赋值、取余(也称求余)、自增、自减
例如:定义了变量,却没有赋值,输出就是undefined
var a;
赋值:=
求余:%
自增:++
自减:–
取余的意思是:一个数字除以另一个数字,除不尽的部分就是余数
例如:5除以2 余数为1
自增分为前置++和后置++,自减也同理
关于自增和自减的一个练习:
var a = 1;
var b;
var sum = (b = a++±-a) + a-- + b++;
答案:5 拆分理解:sum = ( b = 1 + 1) + 1 + 2
7、数组
数组是一个容器,可以存放一个或者多个对象。
创建数组的四种方式:
1、直接量定义数组:使用一对中括号声明一个数组对象,在定义的时候直接对数组进行初始化 (常用)
var arr = [“apple”,“banana”,“orange”];
console.log(arr)
2、采用构造函数:new Array(); 这里是直接创建一个空的数组
var arr = new Array();
arr.push(“aaa”)
arr.push(“bbb”)
console.log(arr)
3、采用构造函数:创建的时候设置初始长度
var arr = new Array(5);
arr[0]=“张三” // 对数组进行赋值
arr[1]=“李四”
console.log(arr) // [‘张三’, ‘李四’, empty × 3]
console.log(arr.length) // 5
4、采用构造函数:创建的时候赋予元素
var arr = new Array(“比亚迪”,“宝马”,“奔驰”,“大众”);
console.log(arr)
数组方法:
push方法:在数组的尾部添加新元素
删除:splice 或 pop
pop方法:删除数组的最后一个元素
splice方法:可插入、删除、替换数组元素 (在原有的数组上进行修改)
splice用前俩个参数进行定位,余下的参数表示插入部分
参数1:数组的下标位置
参数2:要删除元素的个数
示例:
var nums = [1,2,3,4,5];
nums.splice(2,1); // 删除 3 号元素
console.log(nums) // [1, 2, 4, 5]
演示splice的插入元素:
var nums = [1,2,3,4,5];
nums.splice(2,1,38,66); // 把3替换为 38 在38后面添加一个元素 66
console.log(nums) // [1, 2, 38, 66, 4, 5]
元素转字符串:join方法
join是把所有元素放入一个字符串,元素是通过指定分隔符进行分隔的
var str = nums.join(“,”); // 也可以使用其他的 – 555 等等进行分隔
console.log(str) // 1,2,38,66,4,5
拓展:数组的其他方法
concat方法:
将俩个数组或者元素之间连接起来,调用该方法的数组放在前面,方法实参放在后面
var arr1=[1,2,3]
var arr2=[4,5,6]
var arr3 = arr1.concat(arr2)
console.log(arr3) // [1, 2, 3, 4, 5, 6]
pop方法的补充:删除数组中的最后一个元素,切会将这个被删除的元素返回
var del1 = arr3.pop()
console.log(“被删除的元素是:”+del1) // 6
reverse方法:将数组的顺序反转
var arr4 = arr3.reverse()
console.log(arr4) // [6, 5, 4, 3, 2, 1]
shift方法:删除数组的第一项,并返回删除元素的值(和pop进行对比学习)
arr4.shift()
unshift方法:将元素添加到数组开头,并返回数组的长度(和push进行对比学习)
arr4.unshift(115)
slice方法:截取数组的元素,左闭右开(只有一个参数的时候,从当前位置到最后一个元素)
console.log(arr4) // [115, 118, 4, 3, 2, 1]
console.log(“截取数组”)
var arr5 = arr4.slice(1,3) // 118,4
var arr6 = arr4.slice(1) // [118, 4, 3, 2, 1]
map方法:映射—指数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
var arr7 = [1,2,3,4,5];
var arr8=arr7.map(function (x) {
return x*0.9;
})
console.log(arr8) // [0.9, 1.8, 2.7, 3.6, 4.5]
filter方法:过滤—数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
var arr9=arr7.filter(function (x,index) {
return x%3==0 || index>3;
})
console.log(arr9) // 3,5
foreach方法:对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。
参数都是function类型,默认有传参,参数分别为:
遍历的数组内容
第对应的数组索引
数组本身
arr7.forEach(function (x,index,arr) {
console.log(x+’ | ‘+index+’\t’+arr) // 1 | 0 1,2,3,4,5 一直到 5 | 4 1,2,3,4,5
})
every方法:判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
var arr10=arr7.every(function (x) {
return x<10;
})
console.log(arr10) // true
some方法:判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
var arr11=arr7.some(function (x) {
return x<2;
})
console.log(arr11) // true
8、函数七重关
一、函数定义
第一种方式:使用function关键字,后面是方法名,然后函数体
// 定义函数
function test1() { // 函数体
document.write(“My Page”)
}
test1(); // 调用函数
第二种方式:定义一个变量,把函数赋值给变量
var fun1=function () {
console.log(“定义函数的另一种方式”)
}
fun1()
区别:第二种方式必须先定义后调用
JavaScript编译原理
var a = 10;
JavaScript代码在运行之前会经过一个编译的过程,而编译有三个步骤。
1、分词
分词的目的是把这些代码分解为一个个代码块
比如刚才的例子,如果经过分词的步骤,那么得到的结果就是var、a、=、2、;。
2、解析
由JavaScript编译器对刚才分词得到的一个个 代码块进行解析,生成一棵抽象的语法树(AST)。
抽象语法树定义了代码本身,通过操作这棵树可以精准地定位到 赋值语句、声明语句和运算语句。
抽象语法树的创建可以在此网站自行调试和验证。https://esprima.org/demo/parse.html
3、代码生成
JavaScript引擎会把在第二个步骤中生成的抽象语法树进行转换,转换成 什么呢?没错,就是可执行的代码。
二、作用域
作用域:
全局作用域
函数作用域
作用域:就是当你要查找某一个变量的时候,你可以在什么范围呢找到这个变量。这个寻找的范围就是作用域。
不论是全局作用域还是函数作用域,都被定义在词法阶段。
词法阶段就是JavaScript代码编译的第一个步骤–分词。
全局作用域包着一个函数作用域,在函数作用域里面可以访问全局作用域里面的变量。但是反过来的话,全局作用域想要
调用函数作用域中定义的变量却是不可以的。
因此:当发生作用域嵌套的时候,只能里面的访问外面的。
示例:
var five = “星期五”
function five1() {
console.log(“全局变量:”+five)
}
five1()
但是下面这种形式就不是作用域嵌套,因为变量没有定义在函数体中
if(true){
var six = “星期六”
}
console.log(“测试if中的变量:”+six) // 测试if中的变量:星期六
这里并没有出现函数,所以不算作用域嵌套。
if(false){
var seven = “星期六”
}
console.log(“测试if中的变量:”+seven) // 测试if中的变量:undefined
这里undefined是因为代码在分词阶段和解析阶段,变量seven依然会被获取,系统默认给undefined值。
又因为变量seven没有在某一个函数体中,而是在全局作用域中,所以console.log方法可以访问这个变量。
加深理解:
var a = 1;
function test() {
var a;
var inner = function () {
console.log(a) // undefined
}
inner();
}
test();
解析:函数作用域里面嵌套了函数作用域,那么在最里面的inner函数中访问一个变量,就会优先在inner函数里面
寻找,结果却发现找不到。既然在当前函数作用域里面找不到,那么就往上翻一层,在它的父级作用域,也就是test
函数的作用域里面寻找,结果发现找到了。test函数里面定义了一个变量a,但是没有赋值,那么a 就是undefined。
既然已经找到了,那么就不会去全局作用域里面寻找变量a了。所以,全局作用域里面的变量a其实就是一个摆设。
三、参数传递
参数传递:就是函数调用的时候传进来的值
示例:
function add(a,b,c) {
console.log(arguments) // 函数的内部还维护了一个arguments数组 传多个参数都在此数组中
var sum = a + b + c;
console.log(sum)
}
add(1,2,3) // 6 若是传字符串的话会进行拼接
add(1) // NaN a的值是1,b和c的值就是undefined 结果为NaN 代表无法计算
实现多个数字的累加:
function add() {
if(!arguments[0]){ // 如果不存在
return 0;
}
for (var i=1;i<arguments.length;i++){
arguments[0]=arguments[0]+arguments[i]
}
console.log(arguments[0])
}
add(1,2,3,4,5) // 15
方式不唯一:调用函数返回一个结果
function add() {
var sum=0;
for (var i=0;i<arguments.length;i++){
sum+=arguments[i]
}
return sum;
}
var sum= add(1,2,3,4,5,6,7,8,9,10)
console.log(sum) // 55
只传一个参数案例:
function fun(a) {
console.log(a)
}
fun() // undefined
// 进行拆分
function fun() {
var a;</