1标识符 2-5数据类型和数据类型的转化 6算数运算符 7赋值运算符 8自增自减运算符 9关系运算符 10逻辑运算符 11逗号运算符 12三目运算符 13条件语句 14循环语句 15变量作用域 16break和continue关键字 17数组 18函数 19预解析
1.标识符的命名规则
- 只能由字母、数字、_、$组成
- 不能以数字开头
- 不能使用关键字,保留字
2.数据类型
- 基本数据类型
Number Strinng Bolean Undefined Null (数值类型 子字符串类型 布尔类型 未定义类型 空类型) - Object 引用数据类型
- 检测数据类型 typeof
3.转化为数值类型
- string转化number
数值的字符串,数字
' ' 空字符串, 0
数字加其他的字符串,NaN - boolean是true1 false0
- null转化number是0
- undefined转化number是NAN
- 空字符串/false/null转换之后都是0 字符串中不仅仅是数字/undefined转换之后是NaN
- 转化的方法:Number() / +和- / ParseInt()和ParseFloat()
4.转化为字符串类型
- Number和Boolean, 可以通过变量名.toString()
- String(value)
- 常亮or变量 + ' '
5.转化为布尔类型
- string转化Boolean
空字符串' '为false,其他为true - number
0为false,NaN为false - undefined, null都是false
- 空字符串/0/NaN/undefined/null 会转换成false, 其它的都是true
- 方法:Boolean()
6.算数运算符 + - * / %
- 和字符串相加,会拼接字符串
- 和字符串相减,会转化number再运算
- 任何和NaN进行运算,都是NaN
- Bolean Undefined Null参与加减会被强制转化为number类型
7.赋值运算符
- = += -= *= /= %=
例如:res += 1同res = res+1
8.自增自减运算符 ++ --
- 符号在前面,先自增再运算
- 符号在后面,先运算再自增
let num = 1;
// let res = num++ + 1; // let res = num + 1; num++; 2
let res = ++num + 1; // num++; let res = num + 1; 3
console.log(res); //
9.关系运算符 > < >= <= == != === !==
- 返回值Boolean
- 和number比较,转化为number再判断
- 和NaN比较,返回false
- 都是string,比较对应的Unicode编码
- 判断NaN,使用方法isNaN(),因为NaN == NaN或NaN === NaN结果都是false
- 判断取值和类型 === !== 判断取值 == !=
- 关系运算符中 > < >= <= 的优先级高于 == != === !==
- 不能利用关系运算符来判断区间
let res = 10 > 5 > 3; // let res = true > 3; let res = 1 > 3;
10.逻辑运算符
- 与 &&
一假则假
条件A && 条件B
A不成立,返回A(因为判断为false后,就会终止后面的运算) - 或 ||
一真则真
条件A || 条件B
A成立,返回A(因为判断为true后,就会终止后面的运算) - 非!
取反 - &&的优先级高于||
11.逗号运算符
- 在JavaScript中逗号运算符一般用于简化代码
利用逗号运算符同时定义多个变量
let a, b;
利用逗号运算符同时给多个变量赋值
a = 10, b = 5; - 逗号运算符的优先级是所有运算符中最低的
- 逗号运算符的运算符结果就是最后一个表达式的结果
表达式1, 表达式2, 表达式3, ....;
let res = ((1 + 1), (2 + 2), (3 + 3));
console.log(res);//6
12.三目运算符
- 条件表达式 ? 结果A : 结果B;
let res = (1 > 5) ? 1 : 5;
13.条件语句
- if
//第一种形式
if(条件表达式){
条件满足执行的语句;
}
//第二种形式
if(条件表达式){
条件成立执行的语句;
}else{
条件不成立执行的语句;
}
//第三种形式
if(条件表达式A){
条件A满足执行的语句;
}else if(条件表达式B){
条件B满足执行的语句;
}
... ...
else{
前面所有条件都不满足执行的语句;
}
- switch
switch(表达式){
case 表达式A:
语句A;
break;
case 表达式B:
语句B;
break;
... ...
default:
前面所有case都不匹配执行的代码;
break;
}
//例
let day = 7;
switch (day) {
case 1:
console.log("星期1");
break;
case 2:
console.log("星期2");
break;
case 3:
console.log("星期3");
break;
default:
console.log("Other");
break;
}
- if 和switch的选择
几个固定的值使用switch,其他使用if
14.循环语句
- while
while(条件表达式){
条件满足执行的语句;
}
//死循环
while (true){
console.log("123");
}
- dowhile
do{
需要重复执行的代码;
}while(条件表达式);
//dowhile循环的特点: 无论条件表达式是否为真, 循环体都会被执行一次
- for
for(初始化表达式;条件表达式;循环后增量表达式){
需要重复执行的代码;
}
//例如
for(let num = 1;num <= 10;num++){
console.log("次数" + num);
}
//在for循环中"初始化表达式""条件表达式""循环后增量表达式"都可以不写
for(;;){ //for循环是可以省略条件表达式的, 默认就是真
console.log("123");
}
15.变量作用域
- var 定义变量
可以重复定义同名的变量,并且"相同作用域内"后定义的会覆盖先定义的
可以先使用后定义(预解析) - let 定义变量
"相同作用域内"不可以重复定义同名的变量
不可以先使用后定义(不能预解析) - 局部作用域
在函数{}内 - 块级作用域
没有和函数结合在一起{} - 全局变量
省略var或let的变量
在全局作用域中定于的变量
在块级作用域中通过var定义的变量是全局变量 - 局部变量
在局部作用域定于的变量
在块级作用域中通过let定义的变量是全局变量 - 作用域链
变量在作用域链查找规则,就近原则
16.break和continue关键字
- break关键字可以用于switch语句和循环结构中
立即结束当前的switch语句
终止循环 - continue关键字只能用于循环结构
在循环结构中continue关键字的作用是跳过本次循环, 进入下一次循环
for(let num = 1; num <= 10; num++){
if(num === 1){
continue;
console.log("continue后面的代码"); // 永远执行不到
}
console.log("发射子弹" + num);//跳过1
}
17.数组
创建一个数组
通过构造函数创建:let arr = new Array(size);
字面量的方式:let arr = [ ]数组遍历
for(let i = 0; i < arr.length; i++){
console.log(arr[i]);
}数组结构赋值
一般:let [a, b, c] = [1, 3];//c是undefined
给定默认值:let [a, b = 666, c = 888] = [1,2];//b是2
使用扩展运算符(扩展运算符只能写在最后): let [a, ...b] = [1, 3, 5];//b[3,5]数组常用的方法
- 清空数组
let arr = [1, 2, 3, 4, 5];
// arr = [ ];
// arr.length = 0;
// arr.splice(0, arr.length) - 将数组转化为字符串
let arr = [1, 2, 3, 4, 5];
//let str = arr.toString();
// let str = arr.join('分隔符') 默认为',' - 拼接数组
// let arr1 = [1, 3, 5];
// let arr2 = [2, 4, 6];
// let res = arr1.concat(arr2);
// let res = [...arr1, ...arr2]; - 反转数组
arr.reverse(); - 截取数组
arr.slice(start,end)
不包括end
返回值:array 被截取的元素的数组 - 查找索引
arr.indexOf(item,start);
arr.lastIndexOf(item,start);
返回值:number 元素的索引,没有返回-1 - 是否包含
arr.includes(value); - 删除,替换
array.splice(index,howmany,item1,.....,itemX)
改变原始数组
返回值:array 被删除的元素的数组 - 在数组最后增删
array.push(item1, item2, ..., itemX)
改变原始数组
数组的末尾添加一个或多个元素,并返回新的长度
array.pop()
改变原始数组
删除数组的最后一个元素并返回删除的元素
10.在数组开始增删
array.unshift(item1,item2, ..., itemX)
array.shift()
18.函数
- 定义
函数是专门用于封装代码的, 函数是一段可以随时被反复执行的代码块 - 格式
function 函数名称(形参列表){
被封装的代码;
}
//一般
function getSum(a, b) {
console.log(a, b);
return a + b;
}
//保存到变量
let getSum = function (a, b) {
console.log(a, b);
return a + b;
}
- 函数return
return作用结束当前所在函数
函数没有通过return明确返回值, 默认返回undefined - 调用函数时实参的个数和形参的个数可以不相同
- 函数实参的默认值
//es6之前
function getSum(a, b) {
a = a || "1";
b = b || "2";
console.log(a, b);
}
getSum(123, "abc");
//es6之后
function getSum(a = "1", b = getDefault()) {
console.log(a, b);
}
getSum();
// getSum(123, "abc");
function getDefault() {
return "2"
}
- 函数是引用数据类型(对象类型)
- 函数arguments
保存所有传递给函数的实参,例如 console.log(item1,...,itemX);
function getSum() {
// 注意点: 每个函数中都有一个叫做arguments的东东
// arguments其实是一个伪数组
console.log(arguments);
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
}
getSum(10, 20, 30, 40);
- 函数的扩展运算符
- 在左边,将剩余的数据打包到一个新的数组中(解构赋值)
只能写在最后
let [a, ...b] = [1, 3, 5];// a = 1; b = [3, 5]; - 在右边,将数组中的数据解开
let arr1 = [1, 3, 5];
let arr2 = [2, 4, 6];
let arr = [...arr1, ...arr2];// arr = [1, 3, 5, 2, 4, 6]; - 扩展运算符在函数的形参列表中的作用
将传递给函数的所有实参打包到一个数组中
只能写在形参列表的最后
function getSum(...values) {
// console.log(values);
let sum = 0;
for (let i = 0; i < values.length; i++){
let num = values[i];
sum += num;
}
return sum;
}
let res = getSum(10, 20, 30, 40);
console.log(res);
- 函数作为参数和返回值
//作为参数
function a(){
console.log('a');
}
function test(fn) {
fn();
}
test(a);
//作为返回值
function test() {
// 注意点: 在其它编程语言中函数是不可以嵌套定义的,
// 但是在JavaScript中函数是可以嵌套定义的
let say = function () {
console.log("hello world");
}
return say();
}
test();
- 匿名函数
作为其他函数的参数
作为其他函数的返回值
作为一个立即执行的函数
不能够只定义不使用
// 作为其他函数的参数
function test(fn) {
fn();
}
test(function () {
console.log("hello world");
});
// 作为其他函数的返回值
function test() {
return function () {
console.log("hello lnj");
};
}
let fn = test();
fn();
// 作为一个立即执行的函数
(function () {
console.log("hello it666");
})();
- 箭头函数
格式:
let 函数名称 = (形参列表) =>{
需要封装的代码;
}
let say = () => {
console.log("hello world");
}
只有一个形参, 那么()可以省略
let say = value => {
console.log("hello world");
}
只有一句代码, 那么{}也可以省略
let say = value => console.log("hello world"); - 递归函数
递归函数就是在函数中自己调用自己, 我们就称之为递归函数
递归函数在一定程度上可以实现循环的功能
每次调用递归函数都会开辟一块新的存储空间, 所以性能不是很好
//不使用递归
let pwd = -1;
do{
pwd = prompt("请输入密码");
}while (pwd !== "123456");
alert("密码正确");
//使用递归
function login() {
let pwd = prompt("请输入密码");
if(pwd !== "123456"){
login();
}
alert("密码正确");
}
login();
19.预解析
- 浏览器在执行JS代码的时候会分成两部分操作:
预解析以及逐行执行代码,也就是说浏览器不会直接执行代码,
而是加工处理之后再执行,这个加工处理的过程, 我们就称之为预解析 - 预解析的规则
将变量声明和函数声明提升到当前作用域最前面
将剩余代码按照书写顺序依次放到后面
通过let定义的变量不会被提升(不会被预解析)
如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
//var 定义变量预解析
// 预解析之前
console.log(num); //undefined
var num = 123;
// 预解析之后
var num;
console.log(num);
num = 123;
//函数预解析
// ES6之前定义函数的格式
console.log(say);
say();
// ES6之前的这种定义函数的格式, 是会被预解析的, 所以可以提前调用
function say() {
console.log("hello world");
}
// 预解析之后的代码
function say() {
console.log("hello world");
}
//函数赋值给一个var定义的变量
say();
console.log(say);
say(); // say is not a function
// 如果将函数赋值给一个var定义的变量, 那么函数不会被预解析, 只有变量会被预解析
var say = function() {
console.log("hello itzb");
}
var say; //undefined
say();
say = function() {
console.log("hello itzb");
}
- 预解析case
//case1
var a = 666;
test();
function test() {
var b = 777;
console.log(a);
console.log(b);
console.log(c);
var a = 888;
let c = 999;
}
/*
var a;
function test() {
var b;
var a;
b = 777;
console.log(a); // undefined
console.log(b); // 777
console.log(c); // 报错
a = 888;
let c = 999;
}
a = 666;
test();
*/
//case2
//如果变量名称和函数名称同名, 那么函数的优先级高于变量
console.log(value); // 会输出函数的定义
var value = 123;
function value() {
console.log("fn value");
}
console.log(value); // 会输出123
/*
function value() {
console.log("fn value");
}
var value;
console.log(value);
value = 123;
console.log(value);
*/