概念: JavaScript 是运行在js解释器的【解释性】【弱类型】【面向对象】的脚本语言
- js解释器:①嵌入浏览器内核,不需要安装;②独立安装的
- 解释型:运行之前不需要检查语法是否正确,直接运行,碰到错误停止
- 编译型:运行之前需要检查语法是否正确,若不正确则不能运行
- 弱类型:由【数据】决定数据类型,变量可以保存任意数据类型
- 强类型:由数据类型决定保存的数据是什么
- 面向对象:万物皆对象,可以设置属性和方法
作用: 补充css功能;Ajax和服务器能进行交互
注释: //
输出
- 控制台输出 console.log()
- 页面输出 document.write()
- 弹出框输出 alert()
变量&常量
- 变量:
var 变量名=值- 作用:经常使用的数据可以提前保存起来,且数据可随时修改
- 注意:
- 变量名:不以数字开头,不能使用关键字,尽量见名知意
- 创建变量时可不赋值,默认undefined
- 创建变量时可不使用var关键字,直接定义变量 --【全局污染】
- 创建多个变量时,可以用一个关键字var,变量间用“,”连接
- 常量:
const 常量名=值- 注意:一旦创建,值不可修改
数据类型
- 原始/基本/值类型:
- Number 数字,取值:无数个
- String 字符串,取值:无数个
- Boolean 布尔值,取值:true/false
- Undefined 变量的默认值,取值:undefined
- Null 空,用完的变量可以使用null释放
- 引用/对象类型
- String(字符串) Number(数字) Boolean(布尔) - 具有包装类型
- Array(数组) Function(函数) Math(数学) Date(日期) Error(错误) RegExp(正则) Object(面向对象)
- Global - 全局对象:在浏览器端被window对象给代替了:window对象可以省略不写出来
包装类型: 将原始类型的值变为一个引用类型的对象
- 为什么:前辈们发现字符串/数字/布尔经常都会被拿来使用,所以提前提供了包装类型封装为一个引用类型的对象,提供我们一些属性和方法(便于程序员操作)
- 何时使用:只要在你试图用原始类型的值去调用属性或者方法时,会自动套上包装类型
- 何时释放:属性或方法调用完毕后,包装类型自动释放
- 为什么undefined和null不能使用.:不具有包装类型,没有任何的属性和方法
数据类型的转换
Number、String、Boolean
1. 隐式转换
- “+” 若碰到一个字符串,那么两边的数据都会转换为字符串,进行【拼接】操作
- “-*/%” 字符串可以转为数字,但必须是纯数字的字符串,只要包含任一非数字字符,结果则为【NaN】
- 常见转换:true->1 false->0 undefined->NaN "100"->100 "100px"->NaN
- NaN:Not A Number,不是一个数字,但是是Number类型
- 缺点:NaN参与任何算术运算,结果仍为NaN
- NaN参与任何比较/关系运算,结果都为false
- 解决 !isNaN(x);//判断是不是有效数字(true->有效数字)(false->NaN)
2. 显式/强制转换
- 转字符串
xx.toString();//undefined和null不支持String(x);
- 转数字
parseInt(str/num)从左到右依次读取每个字符,碰到非数字字符则停止,并且不认识小数点,若一来就不认识则为NaNparseFloat(str)从左到右依次读取每个字符,碰到非数字字符则停止,认识第一个小数点,若一来就不认识则为NaNNumber()相当于隐式转换
- 转布尔
Boolean();- 只有6个转换结果为false:0,"",undefined,null,NaN,false
运算符
算术运算符
分类:+-*/%
算术运算具有隐式数据类型转换,默认会转为数字。
比较/关系运算符
分类:> < >= <= == != === !==
结果:true、false
比较运算符常用于分支、循环的判断条件之中,比较运算符也具有隐式转换
注意:
- 若参与比较的两个都是字符串,按位比较每个字符的十六进制Unicode号或十进制ASCII码
- 0-9<A-Z<a-z
- 汉字的第一个字:一 4e00(ASCII:19968)
- 汉字的最后一个字:yu 9fa5(ASCII:40869)
- NaN 参与任何比较运算,结果都为false
- !isNaN(x)
- x是一个数字->true;x是NaN->false
- undefined===null
- === 数据类型和数值都相同,结果为false
- ===和!== 无隐式转换
逻辑运算符
分类:&& || !
- && 与
全部条件都为true,结果为true;任一条件为false,结果为false
- || 或
全部条件为false,结果为false;任一条件为true,结果为true
- ! 非
!true -> false
!false -> true
- 短路逻辑 只要前一个条件已经可以得出结论,则后续条件不执行
- && 若前一个条件满足,则后一个操作执行;若前一个条件不满足,则后一个操作不执行
- 用于简化if(){}
条件&&(操作)
- 用于简化if(){}
- || 两个值中二选一,用于兼容
位运算符
- 左移
m<<n 读作:m左移了n位,实际是m*2的n次方
- 右移
m>>n 读作:m右移了n位,实际是m/2的n次方
赋值运算
分类:+=,-=,*=,/=,%=,++,--
- 递增vs累加
- 递增:i++ 一次只能+1
- 累加:i+=n 自定义,每次加n
- i++ vs ++i
- 单独使用时,i++和++i没有区别
- 参与别的表达式时,变量的值会+1,但:++i返回的是+1之后的新值,i++返回的是+1之前的旧值
三目运算
用于简化if...else / if...else if...else
条件?操作1:默认操作
条件1?操作1:条件2?操作2:条件3?操作3:默认操作
注意:
- 只能完成简单分支:操作只有一句话
- 默认操作不能省略
程序的结构
顺序结构
默认,从上向下依次执行每一句代码
分支结构
根据判断条件,选择一部分代码
if
- 一个条件一件事:满足就做,不满足就不做
if(判断条件){
操作;
}
- 一个条件两件事:满足就做第一件,不满足就做第二件
if(判断条件){
操作1;
}else if{
默认操作;
}
- 多个条件多件事:满足哪个就做哪个
if(条件1){
操作1;
}else if(条件2){
操作2;
}else if(条件3){
操作3;
}else{
默认操作;
}
注意:
- 最后的else可以省略,但条件都不满足的时候,分支无效
- 条件有顺序,因为分支只走一条路
switch
switch(变量/表达式){
case 值1:
操作1;
break;
case 值2:
操作2;
break;
default:
默认操作;
}
注意:
- 默认只要满足一条路,会把后面所有操作做完->break:通常放在操作后面
- 最后的default默认操作,不用加break
- 连续多个操作相同,可省略中间部分
- 不具有隐式转换
- default可省略
- switch相对if效率更高,但不能实现范围判断
循环结构
根据判断条件,选择是否重复执行某一段代码
for
for(var 循环变量;循环条件;循环变量的变化){
循环体;
}
循环变量处可以创建多个变量
while
var 循环变量;
while(循环条件){
循环体;
循环变量的变化;
}
do...while
var 循环变量=几;
do{
循环体;
循环变量变化;
}while(循环条件)
循环终止语句
- break 退出整个循环
- continue 退出本次循环
死循环
while(true){循环体}
for(;;){循环体}
执行原理:先判断循环条件,条件为真,执行一次;重复判断至条件为假,才会停止
注意:循环是一次一次执行的,不是同时执行
js的组成
ECMAScript 核心语法
DOM(Document Object Model)文档对象模型 --操作文档
BOM(Browser Object Model)浏览器对象模型 --操作浏览器
作用域
作用域分类
全局作用域: 全局变量和全局函数,在任何位置都可以访问/使用
函数/局部作用域: 局部变量和局部函数,只在当前函数调用时内部可用
作用域的使用规则
优先使用自己的,自己没有找全局,全局没有则报错
- 注意:
- 不要对未声明的变量直接赋值,会导致全局污染
- 所有变量使用前都要先var,不要对没有var的变量直接赋值
- 哪些属于局部变量?
- 直接在函数作用域中创建的变量
- 形参
声明提前
程序执行前,将var声明的变量和function声明的函数集中提前到当前作用域的顶部,但
- 赋值留在原地
- 变量比函数轻,变量在前
按值传递
两个变量之间进行赋值
- 传递原始类型的值:两个变量之间赋值,做操作时互不影响(深拷贝:复制副本)
- 传递引用类型的值【Array、Function】:两个变量之间赋值,做操作时相互影响(浅拷贝:传递地址值)
预定义的全局函数
编码和解码
前端将用户输入的网址的中文【编码】为单字节字符,后端再将前端传递内容【解码】为原文
- 编码
var code=encodeURIComponent("str"); - 解码
var 原文=decodeURIComponent(code);
isFinite(num);
判断num是否再有效范围内,三种情况为false:分母为0,NaN,Infinity
parseInt/parseFloat/isNaN
ES5
1.保护对象
对象的每一个属性都有4大特性
true保存实际值writable开关:控制属性是否可以被修改 默认trueenumerable开关:控制属性是否可以被for in循环 默认trueconfigurable开关:控制属性是否可以被删除 默认true- 一旦被设置为false,则不允许修改其他特性,改为false则不可逆
修改对象的某个属性
Object.defineProperty(xx,"id",{特性})
Object.defineProperties(xx,{
"id":{四大特性},
"name":{四大特性},
"salary":{四大特性}
});
保护对象的三个级别
- 防扩展/防添加
Object.preventExtensions(obj) - 密封(防添加、防删除)
Object.seal(obj) - 冻结(防添加、防删除、防修改)
Object.freeze(obj)
2.数组的新API(简化for循环)
判断
every 每一个都满足(类似&&) 任一为false,则为false
some 任一满足(类似||) 任一为true,则为true
arr.every/some(function(val,i,arr){
return 判断条件
})
注意:
- 三个参数val i arr 并非都需要传入,看需要使用哪些
- val 当前值
- i 当前值下标
- arr 数组本身
- function中的return未写时,默认为undefined
遍历
forEach 直接修改原数组
arr.forEach(function(val,i,arr){
arr[i]*=2;//arr[i]=val*2
})
map 不修改原数组,直接返回新数组
var newArr=arr.map(function(val,i,arr){
return val*2;
})
汇总和过滤
过滤: 筛选出符和条件的元素(不修改原数组)
var subArr=arr.filter(function(val,i,arr){
return 条件;
})
汇总
var subArr=arr.reduce(function(prev,val,i,arr){
return prev*val;
},base)
3.根据一个父对象创建子对象
var 子对象=Object.create(父对象){
"属性1":{四大特性},
"属性2":{四大特性},
"属性3":{四大特性}
}
4.call/apply/bind:替换了函数中的this
call/apply
临时替换了函数中的this,类似“借”。两者的区别为传参形式
call 实参单独传入方法名.call(借用对象,实参)
apply 传入实参整理为数组,传入数组参数方法名.apply(借用对象,[实参])
常用:
Object.prototype.toString.call/apply(数组);Math.max/min.apply(Math,arr);- 将类数组转为普通数组
lis=Array.prototype.slice.call(this)
//摇号
var lis=document.getElementsByTagName("li");
var list=document.getElementsByTagName("ul")[0];
lis=Array.prototype.slice.call(lis);
var nums=[];
while(nums.length<lis.length){
var r=parseInt(Math.random()*(lis.length)+1);
if(nums.indexOf(r)==-1){
nums.push(r)
}
}
lis.forEach((val,i) => val.setAttribute("count",nums[i]));
lis.sort((a,b) => a.getAttribute("count")-b.getAttribute("count"));
lis.forEach(val => list.appendChild(val));
bind
永久替换了函数中的this,类似“买”【不会立即执行】
var 新函数名=方法名.bind(永久绑定的对象,永久绑定的参数,...);
- 创建了一个功能和原函数完全相同的新函数
- 将新函数的this永久绑定为指定对象
- 将新函数中部分固定参数提前永久绑定
5.严格模式
开启严格模式use strict
- 放在作用域顶部
- 严格模式下禁止给未声明变量赋值
- 将静默失败升级为错误
ES6
1.模板字符串
支持直接在字符串中书写变量我的名字叫${name}
2.块级作用域
将var替换为let,用于创建变量
- let前不允许出现未声明的同名变量(解决声明提前)
- 添加了块级作用域,{}相当于一个块
- 绑定事件时记录当前元素下标,不需要自定义下标
for(let i=0;i<lis.length;i++){}
3.箭头函数:简化回调函数
去掉function,()和{}之间添加=>
- 若形参只有一个,省略()
- 若函数体只有一句话,省略{}
- 若函数体只有一句return,return可以省略
- 箭头函数中的this会指向外部的对象
4.for of循环
for(var v of arr){console.log(v)}
- v:value,
- 循环拿到每个值
- 不能遍历hash,不能遍历对象
- 不能直接修改原数组,返回新数组