JavaScript入门①-基础知识筑基

image.png

JavaScript入门系列目录

01、JavaScript基础知识

JavaScript(缩写:JS)是一种具有面向对象能力的、解释型的程序语言,基于对象和事件驱动,具有相对安全性的客户端脚本语言。JavaScript是一门完备的 动态编程语言,当应用于 HTML 文档时,可为网站提供动态交互特性,是前端开发最主要、正式的编程语言。

image

ECMAScript 是由 ECMA 国际标准化组织 制定的一套脚本语言的标准化规范,JavaScript算是他的实现,作为基础语法规范,构成了JavaScript的核心。再加收浏览器提供的DOM(HTML网页内容)操作API、浏览器BOM操作API,共同组成了 JavaScript。

1.1、语法规范

JS代码以行为单位,(半角)分号;结尾。

🔸注释//

  • 单行注释//开头。
  • 多行注释/*多行注释 */(同css)

🔸代码风格

  • 区分大小写,字母、数字、下划线组成,不能数字开头,不能是关键字。
  • 小驼峰命名(推荐):initialColor

🔸关键字: 内置的关键词:如var、do、else、enum、eval、false、for、if、void、function、switch...

🔸语句块:花括号 { 代码块 }

1.2、引用方式

  • 行内JS:元素标签内部的JS代码。
  • 内部JS:定义在<script>标签里的JS代码,可以放到head中、body中、body后,推荐body后,先加载html再执行JS。
  • 外部JS(推荐):单独的JS文件,通过script标签引入,src属性指定JS文件地址,此时标签中写的代码就无效了。
  • 动态加载:通过DOM的API动态加载JS脚本资源,用JS创建<script>标签并引入资源。
<script>属性 描述 值/备注
src 外部资源地址,与嵌入脚本代码不可同时使用 <script src="js1.js" async></script>
type 定义脚本语言类型,可空,默认为JavaScript类型 支持的MIME类型包括text/javascript、 text/ecmascript、 application/javascript 和application/ecmascript
async 异步并行加载,只针对外部JS资源 多个async脚本加载完成的顺序不确定
defer 等HTML解析完成再执行JS,在DOMContentLoaded之前执行,只针对外部JS资源 多个脚本资源顺序加载

🔸脚本加载策略

  • 如果脚本无需等待页面解析,且无依赖独立运行,那么应使用 async
  • 如果脚本需要等待页面解析,且依赖于其它脚本,应使用 defer,将关联的脚本按所需顺序置于 HTML 中。
<body>
    <div>
        <h1>基础语法</h1>
        <input type="button" value="行内JS" onclick="alert('Hello world!');"/>
        <input type="button" value="外部JS调用" onclick="hello();"/>
    </div><hr/>
</body>
<script>
    console.log("内部js:网页加载完成!");
</script>
<!-- 引入外部js文件,设置了src属性,script内部的代码就无效了 -->
<script src="../tstudy/js/js1.js" type="text/javascript" async></script>

02、变量申明var/let/const

变量,就是一个用于存放数值的容器,比如年龄=20,“年龄”就是变量,“20”是他的树值。JS是一种弱类型语言,不需要指明数据类型,用varlet关键字申明即可。

🔸申明方式

  • 申明并赋值,1步完成:var str="hello world";
  • 先申明,再赋值,2步完成。var str1; str1="hello world"; // 默认值为undefined

🔸动态数据类型:JavaScript 是一种“动态类型语言”,意味着一个变量可以被赋值为各种类型数据值,通过typeof判断数据类型。

let age;
console.log(age); //undefined
age =20;
console.log(typeof age); //number
age='年芳二十';
console.log(typeof age); //string
var let (IE11 ES6) const (IE11 ES6)
说明 变量申明 变量申明 只读常量申明:申明时必须初始化值,不可更改
作用域 全局(整个文档)或整个函数体 块级作用域{}包含的区域 块级作用域{}
命名规范 推荐:小驼峰命名 同var 推荐:全大写+下划线,const MAX_SPEED
默认值 undefined undefined 必须赋值
变量提升 提升所有var申明的变量,可以先使用后申明(不推荐),把var变量申明提升到代码头部,⚠️注意不包括赋值 不会提升,顺序执行:必须先申明,后使用。存在暂时性死区
let foo=(foo+55)第二个foo未申明报错
不会提升,顺序执行:必须先申明,后使用。
全局属性 在全局环境时,会成为顶级对象的属性(不可配置属性),作为全局变量存在。
var age=3; //this.age;window.age
重复申明 可以重复申明,覆盖前面的,有点太随意了 不可重复申明,作用域内重复申明会报错
● 包括var、const申明的变量
● 子块可重新申明let,不同的作用域了
● 子块中用var变量会重复,var会提升
不可重复申明,会提示错误,同let
申明多个 支持:var s1=1,st=2; 支持:let s1,s2=2; 支持:const s1=1,s2=2;
性能 一般 一般 编译器会做常量替换优化,提升代码效率
总结 🚫有点粗犷,不推荐 💛更严谨,推荐使用 💚不仅更严谨,性能还好,优先推荐!!!

暂时性死区:由于没有了变量提升,及块级作用域,let、const变量只能在申明后才能用,在这之前不可用,称为“暂时性死区”。

2.1、作用域

特别注意的是 var 作用域在整个文档或函数内,整个文档也可认为是一个特殊的顶级函数。

  • 如下经典的for循环示例,var的变量提升导致输出结果诡异。
for (var i = 1; i <= 5; i++) {
    setTimeout(function () {  //setTimeout为异步执行函数
        console.log(i);	//输出6 6 6 6 6
    }, 0);
}
//换成let,则输出:1 2 3 4 5
//换成const,输出1,然后报错 Assignment to constant variable
  • var作用域在整个函数
function foo() {
    var x = 1; //x作用域在foo函数体内,包括嵌套函数bar也可以访问
    function bar() {
        var y = 2;	//y作用域只在函数体bar
        console.log(x); // 1 
        console.log(y); // 2 
    }
    bar();
    console.log(x); // 1 (`x` 在作用域内)
    console.log(y); // Uncaught ReferenceError: y is not defined
}
foo();
console.log(x); // Uncaught ReferenceError: x is not defined
console.log(y);    // Uncaught ReferenceError: y is not defined
  • let作用域仅限{}块,可以是函数的块function{}、循环的块for{},或者就一个孤独的块{}
let s1;
let s1;  //Uncaught SyntaxError: Identifier 's1' has already been declared
let x = 1; //后面块内的 var x会被变量提升,导致重复变量定义报错
{	
    var x = 2; //Uncaught SyntaxError: Identifier 'x' has already been declared
}

2.2、变量提升

变量提升:JS引擎是先解析代码,获取所有被var申明的变量,然后再逐行执行。只提升用var显示申明的变量,会把所有var的申明提升到全局代码的顶部先执行,⚠️注意只提升申明,不包括赋值。

console.log(sname);  //undefined  只提升了x的变量申明,值为默认值
var sname = "sam";
var x=1;
function print() {
    console.log(sname);  // sam
    console.log(window.sname);  //sam 全局文档中申明的var变量,会作为 window 的全局变量属性
    console.log(this.sname);  //sam 这里的this 指向 全局对象window
}
print();

🔸隐式全局变量:无申明变量(str="hello";),自动提升为隐式全局变量(不论在什么地方),类似var变量,除了没有变量提升。so,🚫尽量不要这么使用,在严格模式下('use strict';)这样写是会报错的。

x = 0;  //未申明变量,成为隐式全局变量
function f() {
    y = 1;  //当执行该函数时,未申明变量,成为隐式全局变量
    var z = 2;  //z是函数内部申明的变量,作用域只在函数体内
}
f();
console.log(x, y); // 0 1
console.log(window.x, window.y); // 0 1
console.log(z);  //Uncaught ReferenceError: z is not defined

2.3、解构赋值

解构赋值是ES6新增的语法,可以一次性给多个变量赋值,提高了编程效率,赋值操作更简洁。具体方式就是:将属性/值从对象/数组中取出,赋值给其他变量的一种赋值方式。有两种解构赋值的语法形式:

  • 数组解构:类似数组的写法,从数组中按顺序赋值,这里数组可以是其他可迭代数据。
  • 对象解构:类似对象的写法,从对象中按属性名赋值。
//变量一个个赋值
let x1 = 1, x2 = 2, x3 = 3, x4 = 4;
// 用数组解构赋值
let [y1, y2, y3, y4] = [1, 2, 3, 4];

[x1, x2] = [x2, x1];	//用来交换x1、x2的值,不用第三方变量
// 从对象解构赋值
let { c, d } = { a: 0, c: 1, d: 2 };

03、基础数据类型

ECMAScript 有 6 种基本类型UndefinedNullBooleanNumberStringSymbol(符号),其他就是都是Object对象类型了,如ArrayobjectMapDatefunction等。

数据类型 描述
Number 数值:整数、小数(浮点型)
● 都是64位浮点类型存储的,最高精度17位,所以1和1.0是相等的。
● 浮点数计算时(小数位)可能不准确,不建议用浮点数做判断。
● 存储时会自动转换整数的浮点数值,如1.0转换为1。
let myAge = 17;
Boolean 布尔类型:有两个值truefalse let isFirstBlood=true;
null 空值关键字,表示空缺、空值,其类型为object,表示一个空对象的指针。undefined继承自null,等值比较时返回true。 注意判断object类型时须排除null。
Undefined 未定义:只有一个值undefined,表示未定义或不存在
● 未赋值的变量默认为undefined
● 调用函数时未传递必须参数,则为undefined
● 函数没有返回值,默认返回undefined
String 字符串:单引号、双引号括起来,用加号+连接字符串。
不可变:JS的字符串一旦创建不可变,所有更改都会创建新的字符串
● 每一个字符元素是16 位的无符号整数值

Symbol ES6 符号类型,具有唯一性不变性,常用于对象属性名 const fooSym = Symbol('foo')
bigint 新添加的数据类型(ES2020)
object对象 对象:引用类型,各种值的组合
 Array 数组对象 var list1=[1,2,3];
 JSON对象 对象:var jobj={name:"zhang",age:1};
 function 函数,本身也是对象 function f1(){/*...*/}

⚠️注意不要将基本类型中的布尔值 true / false 与值为 true/false 的 Boolean 对象弄混了,基本类型Boolean是一个对象。

console.log(typeof 1); //number
console.log(typeof true); //boolean
console.log(typeof null); //object
console.log(typeof undefined); //undefined
console.log(typeof 'abc'); //string
console.log(null == undefined); //true 值比较
console.log(null === undefined); //false  恒等比较
//boolean
const x = new Boolean(false);  //new Boolean()创建了基本类型Boolean的对象,就不是一个平平无奇的值类型了。
console.log(typeof x);  //object
console.log(x.valueOf()); //false valueOf()方法获取对象的基本数据的值
console.log(Boolean(undefined));     //false
console.log(Boolean(null));     //false
console.log(Boolean(NaN));     //false
console.log(Boolean(0));     //false
console.log(Boolean(""));     //false
console.log(Boolean(1));     //true
console.log(Boolean(-100));     //true
console.log(Boolean("abc"));     //true

3.1、Number数字

Number的属性、方法:

属性/方法 描述 示例
🔖静态属性/方法
Number.NaN NaN是一个特殊的Number值,即非数值(Not a Number)
NaN和任何值都不相等,包括它自己,和任何值计算都为NaN
MathparseInt函数执行失败会返回NaN
window.NaN
Number.MAX_VALUE 最大数值(静态属性),值接近于 1.79E+308
Number.MIN_VALUE 最接近 0 的正值,而不是最小的负值,约为 5E-324
Number.isNaN() IE🚫 判断是否等于NaN,window.isNaN是判断是否非数值,坑! 只有NaN才返回true
Number.isInteger() IE🚫 是否为整数
Number.parseFloat() IE🚫 解析浮点数,从第一个非空字符解析获取数字,识别第一个小数点 window.parseFloat()
Number.parseInt() IE🚫 解析整数,从第一个非空字符解析获取数字,支持进制参数 window.parseInt()
🔖构造函数
Number() 转换为数字(忽略空格)。Number()转换数据不同于parseint、parseFloat,要求必须为合法数字,要求更严格,不成功便成仁。 Number(true) //1
🔖实例属性/方法
toFixed(小数位数) 转换为指定小数位数的字符,多了会四舍五入,不足用0补位 n1.toFixed(2)
toString() 转字符串,参数可以指定基数(进制) n2.toString(2) //2进制

📢注意浮点数的精度0.1+0.2 //输出 0.30000000000000004 。由于浮点数的精度问题,永远不要用浮点数值去做条件判断。这种错误是由于IEEE 754标准导致的。

Number.parseFloat("123.4a5"); //123.4
Number.parseInt("123.4a5"); //123
//注意,两个方法是不同的,全局的window.isNaN()是判断是否非数值。
window.isNaN("a") //true
Number.isNaN("a") //false  //这属于JS坑爹的设计,两个含义完全不同

console.log(Number(""));        //0
console.log(Number("123abc"));     //NaN,不同于parseint、parseFloat
console.log(Number("12.12.12"));     //NaN,不同于parseint、parseFloat
console.log(Number.parseFloat("12.12.12"));     //12.12

let n1=1.336,n2=100;
n1.toFixed(2)	//1.34
n2.toFixed(2)	//100.00

window.parseFloat(string):从字符串的第一位(空字符会被忽略)开始,如果是数字(正号+、负号-、数字0-9、第一个小数点.、科学计数法e/E)则转数字,直到非数字或结束。

console.log(parseFloat("123abc"));    //123
console.log(parseFloat("abc123"));    //NaN
console.log(parseFloat("11.11"));      //11.11
console.log(parseFloat("11.11.33"));   //11.11

window.parseint(string):同parseFloat,除了不识别小数点。

console.log(parseInt("123abc"));    //123
console.log(parseInt("abc123"));    //NaN
console.log(parseInt("11.11"));      //11

3.2、String字符串

String:字符串对象,提供各种字符串操作。

属性/方法 描述 示例
🔖构造函数
String() 支持任意值转换为字符串,包括nullundefined,都是直接加引号,很粗暴!📢可以用来判断null、undefined String(null) //"null"
🔖实例属性/方法
length 字符串长度 "abc".length; // 3
charAt(index) 返回指定位置的字符
indexOf(char) 返回字符的索引位置,从前往后找,lastIndexOf是从后往前找 s1.indexOf("12")
substr(start,length?) 截取字符串:指定起始位置长度,无length到结尾(下同) s1.substr(2)
substring(start,end?) 截取字符串:指定起始位置结束位置
slice(start,end?) 截取字符串:起始位置结束位置,同substring,区别是支持负数(倒数),(slice /slaɪs/ 切片) str.slice(0,-1);//截取0到倒数第二位置的字符
split(separator,limit?) 按照分隔符分割字符串为数组 (split /splɪt/ 分裂)
trim() 移除首尾的空白字符,返回新字符,不会改变原有字符。
trimStart() 同上,值移除开头的空白字符,还有移除末尾的trimEnd()
padStart(len,str) 从头补齐字符长度到len,str为去替补的字符,没有则空格 "12".padStart(5,'0')
padEnd(len,str) 补齐字符长度,从尾部开始
replace(old, new) 字符替换,str.replace("台湾","台湾省"),支持正则和函数
repeat(n) 创建一个重复n次的新字符串 "12".repeat(2) //1212
toLowerCase() 字符转小写,大写是toUpperCase()
includes(str) 判断是否包含指定的字符串
startsWith(str) 判断是否以指定字符开头,endsWith()判断结尾
search(str) 字符搜索或正则匹配搜索
match(regexp) 正则匹配搜索字符

🔸字符串的不变性:字符串一经创建不会改变。 let str="abc"; str="123";

  • 这里的不改变,不是字符变量str不能修改,是指字符串"abc"本身不可更改,修改str会创建新的字符。所以,字符的操作都不会影响原来的字符串值,而是创建新的字符串。
  • 字符连接创建新字符:字符的连接,如+,会创建新的字符串。

🔸模板字符串(IE🚫):${var}+反引号 `` 包装

板字符串可以包含特定语法(${expression})的占位符,由一个内置函数负责计算表达式并输出最终的字符串。

let x=1,y=2;
console.log(`sum: ${x} + ${y} = ${x+y}`); //sum: 1 + 2 = 3

🔸JavaScript 特殊/转义字符:在字符串中使用的特殊符号

字符 描述
\0 Null 字节
\b 退格符
\f 换页符
\n 换行符
\r 回车符
\t Tab (制表符)
\v 垂直制表符
\' 单引号
\" 双引号
\\ 反斜杠字符(\)

3.3、类型( 隐式 )转换

隐式类型转转换,是自动进行的,也叫自动类型转换。

字符串 数字 布尔值
undefined "undefined" NaN false
null "null" 0 false
true "true" 1 true
false "false" 0 false
""(空字符) "" 0 false
"1.5" "1.5" 1.5 true
"one" "one" NaN true
0 "0" 0 false
-1 "-1" -1 true(非0数字都true)
1 "1" 1 true
NaN "NaN" NaN false
[](空数组)
0 true
[5]一个数字
里面的数字5 true
["a"][1,2]其他数组 NaN true
{...}对象 NaN true

📢隐式转换总结

  • 转boolean:undefined、null、NaN、0、空字符转bool都为false;非0数字(包括负数)、非空字符(包括”true“、”false“)、对象、空数组[] 转boolean都为true
  • 转数字:非空字符串都是数字(忽略空格)的转对应数字,否则NaN;null、空字符转数字为0。
  • 转字符串:任意类型转字符串加引号,包括undefined、null。
  • +运算:字符串+任意类型(包括空字符)均转换为字符串;boolean、数字转数值进行相加。
  • -*/% 运算:都是隐式转换为数值运算。
  • ==、>、< 比较运算符:不同的值类型转数字;都是字符比较码值;如果存在对象,先转换为原始值。
console.log("-1" - 1); // -2
console.log(2 > true); // true
console.log("one" + true); // onetrue
console.log("1.5" * 2); // 3
console.log("1.5" + 2); // 1.52
console.log([5] / 2); // 2.5

🔸显示类型转换就是调用各种方法、类型构造函数进行显示的数据转换。

  • toString():基本每种数据类型都提供了toString()方法,转换为字符串,除开null和undefined不可使用,会报错。
  • 类型构造函数:Boolean()、Number()、String()的类型函数,都可以转换对应数据类型。
  • valueOf():valueOf()方法可以转换对象为一个基本数据值。
  • 其他如parseInt()、parseFloat()...等方法。

3.4、值类型与引用类型

⁉️堆和栈

  • 栈(stack):提供代码执行环境,并存放值类型、变量标识符。速度快,空间有限(不同浏览器不同)。
  • 堆(heap):存放引用类型数据,速度慢,空间大。
值类型(基本类型) 对象/引用类型
数据类型 undefined、null、Boolean、Number、String、Symbol Array、object、window,function等
包装类型:String、Number、Boolean;
单体内置对象:Global、Math
存储位置 存储在栈中(变量标识符、变量值),占用空间固定
fbc57ebc6a96470b3b45d154cd09382b_1890110-20200327154803560-2032961964.png
存储在堆中,占用空间不固定。变量标识符存储在栈区,值为地址指针,指向存储在堆区的对象数据。
属性方法 不能添加任何属性、方法。 可以动态添加属性和方法
复制 复制变量值 复制地址指针(变量值是对象的指针),指向同一对象
参数传递 值传递,不影响原有变量 引用地址传递,共用同一个对象
垃圾回收 函数执行完就回收了 没有任何引用时,才会被垃圾回收机制收回
类型验证 typeoftypeof 0; //number instanceof[] instanceof Array //true
Object.prototype.toString.call({}) //[object Object]
==比较 值类型是值比较 引用类型比较引用地址,所以要用恒等===比较

image


04、运算/操作符

4.1、➕算数运算符

运算符 描述 示例
+
-
*
/
% 取余数 6%3; //=0
** 指数,幂运算,等同于Math.pow(a,b) 3**2; //=Math.pow(3,2)=9
++ 自加1,符号在前面的先运算,再赋值,在后面的反之 x=++y; //y=1+y; x=y;
x=y++; //x=y;y=1+y;
-- 自减1,同上

📢运算符优先级:[ ++,--,!] > [*,/,% ] > [ +,- ]

var x=1;  //经典面试题
console.log(x+x++ + ++x); //1+1+(1+2)=5

🔸+加运算符会隐式转换+运算就是字符相加、数字相加两种情况

  • boolean、数字相加会隐式转换为数值进行相加。
  • 字符串 + 非字符串会隐式转换为字符串。
console.log(true+false);    //1
console.log(true+3);    //4
console.log(true+"1");    //true1
console.log("123"+123);    //123123
console.log("123"+[1,2,3]);    //1231,2,3

🔸-*/% 隐式转换数值:都是数学运算转数字。减、乘、除、取余运算都是数学运算,会隐式转换为数字再运算。

console.log("123"-"12");    //111
console.log("123"-12);    //111
console.log("123"-1-true);    //121
console.log("123"/true);    //123
console.log("123"/2);    //61.5

4.2、⏸️赋值运算符

运算符 描述 示例
= 赋值运算符,一个神圣的仪式
+= 加法赋值 x+=y //x=x+y
-= 减法赋值 x-=y //x=x-y
*= 乘法赋值 x*=y //x=x*y
/= 除法赋值 x/=y //x=x/y
%= 取余赋值 a%=3 //a=a%3

4.3、🔀比较运算符

运算符 描述 示例/备注
>,<,>=,<= 大于,小于,大于等于,小于等于
== 相等比较,比较变量的值,而不管其类型 "1"==1; //true
=== 恒等比较,比较类型和值 无类型转换
!= !=不等于比较
!== !==不恒等比较 无类型转换

比较运算符会隐式转换为数值

  • 都是字符,转为码值进行比较,
  • 两个不同类型比较,隐式转为数值,然后进行比较。
  • 引用类型永远不相等,虽然其内部的数据一模一样,因为比较的是引用地址。
  • 推荐恒等,由于 ==!= 比较会隐式转换,会遇到较多奇葩问题,在开发中,我们一般使用严格比较恒等 === !==
  • NaN与任何值比较,都是false, Infinity 只等于它自身。console.log(NaN==NaN); //false
  • null 和 undefined, 他们直接相等,和其他原始类型比较,不相等。
console.log("123">"45");    //false 都是字符比较字符码值
console.log("123">45);  //true  转换为数值比较
console.log("123"==123);    //转数值比较,true
console.log(""==false);  //true 转为数值比较
console.log("false"==false);  //false 转为数值比较
console.log("true"==true);  //false 转为数值比较
console.log([1,2,3]==[1,2,3]);  //false,数组是对象

4.4、❗逻辑运算符

运算符 描述 示例/备注
! !逻辑非运算符 !false //true
&& &&|| 也叫短路运算符:从左往右判断,符合要求就不继续执行了
逻辑与&&=同时满足:返回第一个为false的值,否则最后一个值
1 && 2 && 3 //返回3
1 && 2 && false && 3 //返回false
|| 逻辑或=满足一个即可:返回第一个为true的值,否则最后一个值 1 || 2 || false //返回1

逻辑运算符会隐式转换为boolean值。

短路运算符&&||常用来判断都为真、至少有一个为真:

let user = { name: "sam", score: 98, age: 12 };
if (user.age <= 12 && user.score > 95)
    console.log(`${user.name} 是一个少年天才!`);

4.5、⁉️其他操作符

运算符 描述 示例
?: 三元表达式判断条件 ?条件为真 :条件为假 age = 4 > 2 ? 4 : 2; //4
??= 逻辑空赋值运算符: (x ??= y) 仅在 x 是(null 或 undefined) 时对其赋值y x??="default";
?. || 可选链运算符,不为空(null 或 undefined)时才执行。可以没有 ||,返回undefined page=res?.data?.size ||1;
obj?.[prop]; obj.func?.()
void 运行表达式,返回一个 undefined void alert("void")
&,|,~,^,<<,>> 二进制位的运算,32位数字的位运算
delete 删除一个对象的属性、数组键值,删除后会变为undefined delete objt.pro
typeof 获取数据类型,typeof (operand),括号省略。 typeof null; //object
in 判断属性是否在对象中 "length" in [] //true
instanceof 判断对象是否指定的类型,用于引用类型、自定义类型 [] instanceof Array //true
new new Object()创建对象实例
superIE🚫 调用一个对象父类的函数,在子类中调用 supper.print();

05、逻辑语句

if/switch条件判断

if条件语句,根据条件执行。if可单独使用,也可以跟else if (0个或多个,中间)、else(0个或1个,放最后)。

if (条件) { /*代码*/ }
else if(条件) { /*代码*/ }
else if(条件) { /*代码*/ }
else { /*代码*/ }  //可以不要else部分,单独if

switch定值条件分支,值的判断是用的===恒等比较,多用于枚举值、固定的常量值。注意每一个case后需要用break,以防止穿透(继续往后执行)。

switch (表达式) {
    case 值1:
        /*代码*/;
        break;     //返回,结束switch,防止无意义的穿透执行
    case 值2:
    case 值3:      //可以多case合并一块
        /*代码*/;
        break;
    default:      //前面的case都没有命中时执行
        /*代码*/
}

try.catch异常处理

try...catch...finally 语句捕获异常,throw语句抛出一个异常。

  • JS代码如果发生了异常,则不会再执行后面的代码了,就需要做好异常捕获处理。
  • finally 语句块为可选,不管是否抛出异常都会执行,常用来做一些清理收尾工作。
  • throw抛出异常,可以是自定义的值、对象,可以用Error对象包装一个错误信息。
function print(para) {
    if (para <= 0) {
        throw "参数para必须大于0(para= "+para+")";
        throw new Error("参数para必须大于0(para= "+para+")");
    }
    console.log(para);
}
print(2);   //如果这里参数用-2,则会抛出异常,这里的异常没人管,后面的代码就不会执行了
try{        //try包装要执行的代码
    print(-2);
}
catch(e){   //catch捕获try中抛出的异常并处理,参数为捕获到的异常信息,如果没有异常则跳过catch语句
    console.log("发生错误:" + e);
}
finally{
    console.log("执行完毕!")    //始终会被执行的代码,用于一些清理收尾工作
}

break/continue

  • break结束循环,停止本层循环,跳出本层循环,大家都别干了!
  • continue结束本次循环,暂停本次循环,不执行后面的代码了,继续下一次循环,我不想干了,你们继续!

while(true)

while循环,先判断,符合条件才执行,会循环的判断条件 执行,所以必须注意结束循环的控制,不然就是死循环了。

while(条件表达式){
    /*循环代码*/
    //条件控制代码,别忘了
}

do{ } while (true)

do...white循环,先执行 再判断。同while,需注意循环的控制,避免死循环。

do{
    /*循环代码*/
    //条件控制代码,别忘了
}while(条件表达式)

for(i,i<n,i++){ }循环

循环执行逻辑控制语句:

for(初始化语句;判断条件语句;控制条件语句){
    /*循环代码*/
}
for(let i=1;i<=10;i++){ //循环1到10
    if(i>6)
        break; //跳出并结束循环
    if(i%2==1)
        continue;   //如果是奇数,返回继续下一次循环
    console.log(i);     
}

for(in){ }可枚举属性

for...in循环,对一个对象(不仅仅是数组)进行循环遍历,遍历其所有可枚举的属性(索引下标、属性),包括继承来的。

let arr=[1,2];
arr.uname="arr";
arr.print=function(){console.log(this.length)};
for(let i in arr){
    console.log(i+":"+arr[i]);
}
/*输出:
0:1
1:2
uname:arr
print:function(){console.log(this.length)}
*/

❗慎用 for(in):for(in)是循环遍历的是所有可枚举的(enumerable)属性,对于数组、可迭代集合一般使用for(of)

for(of) {}集合值迭代

for…of(IE🚫)语法是ES6新引入的语法,用于遍历可迭代(iterable)对象,只遍历数组对象元素。包括字符串String、数组Array、集合Set、字典Map、arguments 对象、DOM NodeList 对象等。

for...in最大的区别就是,for...of迭代的是集合的数据值,而不是可枚举属性(索引)。

let arr=[1,2];
arr.uname="arr";
arr.print=function(){console.log(this.length)};
for(let i of arr){
    console.log(i); //1  2
}

forEach()数组方法

forEach 作用于数组对象,用于遍历数组对象的每一个元素,并对每一个元素执行回调(callback)函数。

语法:ArrayObject.forEach(callback(currentValue, index, arr), thisValue))

let arr = [1, 2];
arr.uname = "arr";
arr.print = function () { console.log(this.length) };
arr.forEach(function (item, index) {
    console.log(index + ":" + item);
});
/*输出: 
0:1
1:2
*/

©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

posted @ 2022-11-30 11:23  安木夕  阅读(989)  评论(0编辑  收藏  举报