Vinson

Vinson

JavaScript 基本概念

发表于 2023-08-06
Vinson
阅读量 26

JavaScript 变量

var 关键字

var message; // 默认 undefined
js

声明后可以改变类型,但不推荐

var message = "hi";
message = 100; // 合法,但不推荐
js

var 声明作用域,一个函数内部定义一个变量,在函数退出时被销毁

function test() {
  var message = "hi"; // 局部变量
}
test();
console.log(message); // 出错!
js

在函数内定义变量时省略var 操作符,可以创建一个全局变量:

function test() {
	message = "hi"; // 全局变量
	// 在严格模式下,如果像这样给未声明的变量赋值,则会导致抛出ReferenceError。
}
test();
console.log(message); // "hi"
js

定义多个变量

var message = "hi",
found = false,
age = 29;
//在严格模式下,不能定义名为eval 和arguments 的变量,否则会导致语法错误。
js

var 声明提升

function foo() {
    console.log(age);
    var age = 26;
}
foo(); // undefined
js

关键字声明的变量会自动提升到函数作用域顶部,相当于:

function foo() {
	var age;
    console.log(age);
    age = 26;
}
foo(); // undefined
js

反复多次使用var 声明同一个变量也没有问题

function foo() {
    var age = 16;
    var age = 26;
    var age = 36;
    console.log(age);
}
foo(); // 36
js

let 声明

let 声明的范围是块作用域:

if (true) {
    var name = 'Matt';
    console.log(name); // Matt
}
console.log(name); // Matt

if (true) {
    let age = 26;
    console.log(age); // 26
}
console.log(age); // ReferenceError: age 没有定义
js

不能重复声明

let age;
let age; // SyntaxError;标识符age 已经声明过了
js

块作用域没有重复声明则使用相同标识符则不会报错

var name = 'Nicholas';
  console.log(name); // 'Nicholas'
if (true) {
  var name = 'Matt';
  console.log(name); // 'Matt'
}
let age = 30;
console.log(age); // 30
if (true) {
  let age = 26;
  console.log(age); // 26
}
js

两个关键字不能重复声明

var name;
let name; // SyntaxError
let age;
var age; // SyntaxError
js

暂时性死区

// name 会被提升
console.log(name); // undefined
var name = 'Matt';
// age 不会被提升
console.log(age); // ReferenceError:age 没有定义
let age = 26;
js

全局声明

let 在全局作用域中声明的变量不会成为window 对象的属性(var 声明的变量则会)

var name = 'Matt';
console.log(window.name); // 'Matt'
let age = 26;
console.log(window.age); // undefined
js

注意
不过 let 声明还是在全局作用域中发生的,变量会在整个页面生命周期内续存。所以不要重复声明同一个变量,避免 SyntaxError

条件声明

<script>
    var a = 1;
    let b = 2;
</script>
<script>
    console.log(a); // 1
    console.log(b); // 2
</script>
js

JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。但是 let 是块级作用域,所以检查不到之前是否声明过。

<script>
    var name = 'Nicholas';
	let age = 26;
</script>
<script>
    // 假设脚本不确定页面中是否已经声明了同名变量
    // 那它可以假设还没有声明过
    var name = 'Matt';
    // 这里没问题,因为可以被作为一个提升声明来处理
    // 不需要检查之前是否声明过同名变量
    
    let age = 36; // age 之前声明过,这里会报错
</script>
js

try/catch 语句或typeof 操作符也不能解决

<script>
    let name = 'Nicholas';
    let age = 36;
</script>
<script>
  if (typeof name === 'undefined') {
    let name; // name 被限制在if {} 块的作用域内
  }
  name = 'Matt'; // 因此这个赋值形同全局赋值
  try {
    console.log(age); // 如果age 没有声明过,则会报错
  }
  catch(error) {
    let age; // age 被限制在catch {}块的作用域内
  }
  age = 26; // 这个赋值形同全局赋值
</script>
js

for 循环中的let 声明

使用 var 时变量会渗透到外面

for (var i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // 5
js

let 之后则不会,因为遇到 {} 就会形成作用域块

for (let i = 0; i < 5; ++i) {
// 循环逻辑
}
console.log(i); // ReferenceError: i 没有定义
js

常见的异步循环问题

for (var i = 0; i < 5; ++i) {
	setTimeout(() => console.log(i), 0)
}
// 你可能以为会输出0、1、2、3、4
// 实际上会输出5、5、5、5、5
js

在延迟定时器执行时,他是异步的,循环已经结束了,最后的值始终都是 5。

使用 let 才是期望的值

for (let i = 0; i < 5; ++i) {
	setTimeout(() => console.log(i), 0)
}
// 会输出0、1、2、3、4
js

每次迭代循环声明一个新的迭代变量,每个setTimeout 引用的都是不同的变量实例。这种风格也适用于 for in、for of。

const 声明

const 的行为与let 基本相同,但是他是常量,声明之后不能修改,尝试修改const 声明的变量会导致运行时错误。

const age = 26;
age = 36; // TypeError: 给常量赋值

// const 也不允许重复声明
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError

// const 声明的作用域也是块
const name = 'Matt';
if (true) {
	const name = 'Nicholas';
}
console.log(name); // Matt
js

但是 const 声明只限制声明的引用:

const person = {};
person.name = 'Matt'; // ok
js

在 for 中 const 与 let 一样分别独立创建变量的实例,但是不能用 const 来迭代变量(因为变量 i 要自增)

for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值
js

只想用const 声明一个不会被修改的for 循环变量,那也是可以的

let i = 0;
for (const j = 7; i < 5; ++i) {
  console.log(j);
}
// 7, 7, 7, 7, 7
for (const key in {a: 1, b: 2}) {
  console.log(key);
}
// a, b
for (const value of [1,2,3,4,5]) {
  console.log(value);
}
// 1, 2, 3, 4, 5
js

最佳实践
不使用var,const 优先,let 次之

JavaScript 严格模式及运算问题

严格模式

"use strict"; 
// 函数体 告诉支持 JavaScript 引擎切换到严格模式
// 这样写即使低版本的浏览器不支持严格模式也不会报错,他只是个字符串
js
  1. 全局变量声明必须加 var。 必须先声明再使用。
  2. 函数内重名属性
  3. arguments 对象不被允许修改,只会是传进来的数值
  4. fn.caller,arguments.callee 不可用
  5. 函数本身不能使用 this 关键字
  6. eval() 里存在作用域
  7. 新增保留字:implements,interface,let,package,private,protected,public,static,yield。

运算的问题

// 8 进制  以 0 开头 代表 8 机制
var n4 = 070;// 56
// 16 进制  以 0x 开头  代表 16 进制
var n5 = 0x1f;// 31

// NaN Not a Number 不是一个数字
console.log(typeof NaN);// number
console.log('我' + 10);// '我 10'
console.log('wo' - 20);// NaN
console.log(0 / 20);// 0
console.log(20 / 0);// infinity 无限

// 浮点运算的问题
console.log(0.1 + 0.2);// 0.30000000000000004
console.log(0.1 + 0.2 == 0.3);// false
console.log(0.07 * 100);// 7.00000000001
js

JavaScript 在 HTML 中的引入

script 这个元素是由网景公司创造出来,最早在Netscape Navigator 2 中实现。

  • charset:src 属性指定的代码字符集。大多数浏览器无视它的值。
  • crossorigin:配置CORS(跨域)设置,"anonymous"请求不设置凭据标志,"use-credentials"设置凭据标志,跨域请求会包含凭据。
  • defer:脚本延迟到文档被解析和显示之后再执行! defer 属性只适用于外部脚本文件
  • async:表示立即下载脚本,页面其他操作不影响! async 属性只适用于外部脚本文件
  • integrity:验证子资源完整性。
  • language:废弃。表示代码块中的脚本语言
  • src:要执行的代码的外部文件
  • type:代替language,表示代码块中的MIME 类型。默认"text/javascript",实际上"text/javascript"和"text/ecmascript"已经废弃了。JavaScript 文件的MIME 类型通常是"application/x-javascript",不过给type 属性这个值有可能导致脚本被忽略。如果这个值是module,则代码会被当成ES6 模块,而且只有这时候代码中才能出现import 和export 关键字。
  • 不能再任何地方出现 ,浏览器遇到 时会认为这是结束的标签
  • 解决方法 通过转义字符 \ 解决这个问题
alert("<\/script>");
js

异步脚本

<!-- 标记 async 的脚本不保证加载的先后顺序,第二个脚本可能会在第一个先执行  -->
<script src="js1.js" async></script>
<script src="js2.js" async></script>
html

推迟脚本

<!-- 两个js标签会在浏览器解析到结束的</html>标签后才会执行 -->
<script defer src="example1.js"></script>
<script defer src="example2.js"></script>
html

动态脚本

let script = document.createElement('script');
script.src = 'gibberish.js';
document.head.appendChild(script);
// 元素添加到DOM之前不会发送请求,默认异步加载(相当于添加了async属性)
js

统一动态脚本加载行为(不一定都支持async属性):

let script = document.createElement('script');
script.src = 'gibberish.js';
script.async = false;
document.head.appendChild(script);
js

让浏览器预先加载js文件,js动态加载js脚本浏览器并不知道,想要浏览器知道这个文件的存在可以在文档头部添加:

<link rel="preload" href="gibberish.js">
<!-- 这会提高浏览器获取资源队列的优先级 -->
html

JavaScript 数值转换

数据类型 转换为 true 的值 转换为 false 的值
Boolean True False
String 非空字符串 ‘’
Number 非 0 数字 0 和 NaN
Object 任何对象 null
Undefined n/a(不适用) Undefined

isNaN

  • 不能被 number 转换为数字 ----> true
  • 能被 number 转换为数字 ----> false
isNaN(NaN) // true 
isNaN("blue") // true (不能被转换为数字)
isNaN(10) // false
isNaN("10") // false (10可以被转换成数值10)
isNaN(true) // false(可以被转换成1)
js

isNaN 首先会调用对象的 valueOf() 方法,然后再确定返回的值是否可以转换为数值。如果不能,再调用 toString() 方法,并测试其返回值

isFinite

NaNInfinity 都返回 true
isFinite(NaN) // false
isFinite(Infinity) // false
js

Number

  • 转换为为数值 无法转换 —> NaN(不是一个数字)
Number("hello") // NaN
Number("0011") // 11
Number("") // 0
Number(true) // 1

let intNum = 55; // 整数

// 八进制第一个数字必须是零(0),然后是相应的八进制数字(数值0~7)
let octalNum1 = 070; // 八进制的56
let octalNum2 = 079; // 无效的八进制值,当成79 处理
let octalNum3 = 08; // 无效的八进制值,当成8 处理

// 十六进制字面量,必须让真正的数值前缀0x(区分大小写),然后是十六进制数字(0~9 以及A~F)
let hexNum1 = 0xA; // 十六进制10
let hexNum2 = 0x1f; // 十六进制31
js

parseInt

  • 转换为整数
    • 参数 1:要转换的变量
    • 参数 2:以什么进制来转换这个数值,默认 10 进制,0 也是 10 进制
parseInt("234blue") // 234
parseInt("blue234") // NaN
parseInt("") // NaN
parseInt("44.5") // 44
parseInt("070") // 56(8进制)
parseInt("0xf") // 15(16进制)
parseInt("070" , 10) // 后面告诉浏览器这是10进制
js

parseFloat

  • 转换为小数,只解析 10 进制,没有小数点或小数点后面都是 0 会返回整数
parseFloat('1234blue') // 1234 整数
parseFloat('0xA') // 0
parseFloat('22.54.5') // 22.54
js

toString

  • 转换为字符串 不能转换 null 和 undefined
11.toString() // '11' 字符串
true.toString() // 'true' 字符串
toString() // 是对象下的方法,所以不能使用
js

String

  • 转型函数 能转换 null 和 undefined
String(null) // "null
String(undefined) // "undefined"
11 += ""; // "11" 字符串
js
  • +‘’ 拼接也可以转换为 string

JavaScript 数据类型检测

typeof

  • 基本数据类型适用,引用数据类型会检测成 object
  • typeof 会返回字符串
  • "undefined"表示值未定义;
  • "boolean"表示值为布尔值;
  • "string"表示值为字符串;
  • "number"表示值为数值;
  • "object"表示值为对象(而不是函数)或null;
  • "function"表示值为函数;
  • "symbol"表示值为符号。
String ----> string
Number ----> number
NaN   ----> number
Boolean ----> boolean
undefined----> undefined
null  -----> object
Object -----> object
Array  -----> object
function-----> function

typeof typeof 123 // string

// typeof 是一个操作符而不是函数,所以不需要参数(但可以使用参数)。
typeof 'message' // "string"
typeof('message') // "string"
typeof null // "object" 这是因为特殊值null 被认为是一个对空对象的引用
js

instanceof

  • 根据原型链来识别返回 true 或 false
person instanceof Object // 变量person是Object吗
person instanceof Array // 变量person是Array吗
js

判断是否是数组

let arr = [];

arr instanceof Array // true
arr.constructor === Array // true
arr.__proto__ === Array.prototype // true
Array.isArray(arr) // true
Object.prototype.toString.call(arr) // '[object Array]'
Array.prototype.isPrototypeOf(arr)// true
js

Object.toString 判断

  • 利用顶级对象 toString 方法改变 this 指向判断数据类型
Object.prototype.toString.call([])// [object Array]
Object.prototype.toString.call(2)// [object Number]
Object.prototype.toString.call(Function)// [object Function]
js

Undefined 类型

当使用var 或let 声明了变量但没有初始化时,就相当于给变量赋予了undefined 值

let message; // undefined
console.log(message == undefined); // true
console.log(age); // 报错,没有声明

// 对未声明的变量,只能执行一个有用的操作,就是对它调用typeof
console.log(typeof age); // "undefined" 未声明
// 所以初始化的时候赋值,typeof 来检查某个变量是否未声明

// 未声明的变量调用 delete 也不会报错
delete a
js

Null 类型

null 值表示一个空对象指针,typeof null 会返回"object"

console.log(typeof null); // "object"
js

使用 null 来初始化对象,只需要判断是不是null就可以知道是否被赋值引用

let car = null;
if (car != null) {
  // 一些操作
}
js

undefined 值是由null 值派生而来的,因此ECMA-262 将它们定义为表面上相等

console.log(null == undefined); // true 
//(==)比较null 和undefined 始终返回true
js

JavaScript 运算符

ECMAScript 中的操作符比较独特,包括字符串、数值、布尔值,甚至还有对象。应用给对象时通常会调用会调用valueOf()或toString()方法。

一元运算符

递增/递减

++n // 先自增 1,再运算
n++ // 先运算,再自增 1
--n // n-- 同理
!n // 转换为 Boolean 值
js

操作符在前,先自递增/递减后再进行运算。

let num1 = 2;
let num2 = 20;
let num3 = --num1 + num2;
let num4 = num1 + num2;
console.log(num3); // 21
console.log(num4); // 21
js

操作符在后,先运算再进行自递增/递减。

let num1 = 2;
let num2 = 20;
let num3 = num1-- + num2;
let num4 = num1 + num2;
console.log(num3); // 22
console.log(num4); // 21
js
let s1 = "2"; // 是有效的数值形式:则转换为数值再应用改变。
let s2 = "z"; // 不是有效的数值:则将变量的值设置为NaN 。
let b = false; // 如果是false,则转换为0 再应用改变。如果是true,则转换为1 再应用改变。
let f = 1.1; // 对于浮点值,加1 或减1。
let o = {  // 开头说过,如果是对象,valueOf()方法取得可以操作的值,再应用上面的规则。如果是NaN,则调用toString()并再次应用其他规则。
  valueOf() {
    return -1;
  }
};
s1++; // 值变成数值3
s2++; // 值变成NaN
b++; // 值变成数值1
f--; // 值变成0.10000000000000009(因为浮点数不精确)
o--; // 值变成-2
js

一个变量同时等于两个值

参考上面所说的,如果是对象,操作符会先调用 valueOf 取值,重写 valueOf 即可使 o == 1 且 o == 2

let o = {
  a:0,
  valueOf() {
    return ++this.a
  }
};
if(o == 1 && o == 2){ // true
  console.log('yes')
}
// yes
js

一元加和减

let s1 = "01";
let s2 = "1.1";
let s3 = "z";
let b = false;
let f = 1.1;
let o = {
  valueOf() {
    return -1;
  }
};
s1 = +s1; // 值变成数值1
s1 = -s1; // 值变成数值-1
s2 = +s2; // 值变成数值1.1
s2 = -s2; // 值变成数值-1.1
s3 = +s3; // 值变成NaN
b = +b; // 值变成数值0
f = +f; // 不变,还是1.1
f = -f; // 变成-1.1
o = +o; // 值变成数值-1
js

算术运算符

  • + 加法比较特殊
    • 两边都是数字时,做数学运算
    • 一边为字符串,进行字符串连接
    • 一边为对象类型 object,将对象使用 toString 方法转换为字符串,进行连接
    • - * / % 只能数学运算 隐式用 Number 转换 不能转 ---> NaN
alert([10] + 10);           // '1010'
alert([1,2,3] + 10);        // '1,2,310'
alert({name:'joth'} + 10);  // '[object Object]10'
alert(null + 10);           // 10
alert(undefined + 10);      // NaN
alert(true + 10);           // 11

alert(null - 10);           // -10
alert(undefined * 10);      // NaN
alert([10,20] / 10);        // NaN

alert(1 % 0);               // NaN
alert(100 % null);          // NaN
js

比较运算符

  • 大于 >,小于 <,大于等于 >=,小于等于 <=, 等于 ==,全等 ===,不等于 !=,不全等 !==。
  • == 等于时:只需要值相等,不用管数据类型,实际上也是通过 Number 进行类型转换
  • === 全等时:不会进行数据类型转换 那么需要两边的数据类型和值都相等
  • 特例 undefined == null 为真( js 真理)undefined 值是由null 值派生而来的,因此ECMA-262 将它们定义为表面上相等
'10' == 10// true
'10' === 10// false
undefined == null// true 
undefined === null// false 数据类型不同
js

逻辑运算符

  • 非 ! 取反 非真为假 非假为真
  • 与 && 与运算见假则假
  • 或 || 或运算见真则真
!false// true
!!false// false

// 与运算:与运算见假则假
true && false// false
false && true// false
false && false// false
true && true// true

// 或运算:或运算见真则真
true || false// true
false || true// true
true || true// true
false || false// false
10 > 3 && '10' > '3'// false
js

短路运算

  • 短路与: 第一个值为true 返回第二个值, 第一个值为false,则返回第一个值
  • 短路或: 第一个值为true 返回第一个值, 第一个值为false,则返回第二个值
// 短路与
10 && null// null
undefined && 'abc'// undefined

// 短路或
10 || null// 10
undefined || 'abc'// 'abc'
js

三目运算符

  • 方法: ? : —> 判断条件 ? 当条件为真时 返回的值 : 当条件为假时返回的值
var y = -20 > 0 ? 1 : -20 == 0 ? 0 : -1;
js

赋值运算符

  • = 赋值 += -= *= /= %=
a += 5;  // 等价于 a = a + 5;
a -= 10; // 等价于 a = a - 10;
a *= 3  // 等价于 a = a * 3
a /= 2  // 等价于 a = a / 2
a %= 2  // 等价于 a = a % 2
js

隐式类型转换

  • + - * / %
  • + 转换方式比较多
  • - * / % 都是使用 Number 转数字 能转数字就运算 不能转数字就 NaN

括号/逗号运算符

var a = (1,2,2,1,0) // 0 返回最后一项
js
  • 应用
const arr = [{a: 1},{a: 2}];
arr.reduce((prev,next) => (prev+=2, prev + next.a),0) // 7
js

指数运算符

  • ES2016 新增了一个指数运算符(**)
2 ** 2 // 4
2 ** 3 // 8

2 ** 3 ** 2 // 512,相当于 2 ** (3 ** 2)
a **= 2; // 等同于 a = a * a;
b **= 3; // 等同于 b = b * b * b;
js

位操作符

ECMAScript中的所有数值都以IEEE 754 64 位格式存储
但位操作并不直接应用到 64 位表示,而是先把值转换为 32 位整数,位操作之后再把结果转换为64 位。(所以只需要考虑 32 位)
32 位,前面 31 位表示数值,32 位表示数值的符号,0 表示正,1 表示负。(称为符号位)
正值以二进制格式存储,31 位都是 2 的幂。(第一位 2º,第二位 2¹,以此类推)
数值 18 用二进制来表示为 00000000000000000000000000010010(32 位数),前面的 0 可以省略 10010。
10010 = (2^4 * 1)+(2^3 * 0)+(2^2 * 0)+(2^1 * 1)+(2^0 * 0) = 18

负数以二补数(补码)储存

  1. 以绝对值的二进制表示(-18先确定18的二进制)
  2. 0 变成 1,1 变成 0(称为补数/补码)
  3. 给结果加 1
    按上述步骤表示 -18:

第一步:表示绝对值 18

0000 0000 0000 0000 0000 0000 0001 0010

第二步:补码

1111 1111 1111 1111 1111 1111 1110 1101

第三部:给补数加 1

1111 1111 1111 1111 1111 1111 1110 1110 (这就是 -18 的二进制表示)

let num = -18;
console.log(num.toString(2)); // '-10010'
js

输出’-10010’,这个过程会求处二补数,然后符合逻辑的表示出来。ECMA中存在无符号的整数,也就是说无符号的整数比有符号的范围更大,因为符号位可以用来表示数值。

按位非

~ 来表示,作用是返回数值的补数。

let num1 = 25;    // 二进制00000000000000000000000000011001
let num2 = ~num1; // 二进制11111111111111111111111111100110 这里取反后还减了 1
console.log(num2); // -26
js

这样的结果比-num1 - 1结果更快,位操作符是在底层表示进行的。

应用

let a = 25.513
~~a // 25 取整
let b = 5.9
~~b // 5 取整
js

~a 反补减 1 得 -26,再~ 反补得到正 26 减 1 得到 25。

按位与

& 来表示,两个数的位 1 1 得 1,0 1 得 0, 0 0 得 0。

let result = 25 & 3;
console.log(result); // 1
js

25 = 0000 0000 0000 0000 0000 0000 0001 1001

3 = 0000 0000 0000 0000 0000 0000 0000 0011

只有都为 1 时二进制位才取 1

0000 0000 0000 0000 0000 0000 0000 0001

所以结果就是 1

按位或

| 来表示,看懂了按位与那么按位或也是同理。有一个位为 1 则为 1,都为 0 时则为 0。

let result = 25 | 3;
console.log(result); // 27
// 25 = 0000 0000 0000 0000 0000 0000 0001 1001
//  3 = 0000 0000 0000 0000 0000 0000 0000 0011
// 得   0000 0000 0000 0000 0000 0000 0001 1011
// 11011 等于27
js

按位异或

^ 来表示,它只有在一位是 1,一位是 0 时才会得 1。都是 0 或都是 1 则得 0。

let result = 25 ^ 3;
console.log(result); // 26
// 25 = 0000 0000 0000 0000 0000 0000 0001 1001
//  3 = 0000 0000 0000 0000 0000 0000 0000 0011
// 得   0000 0000 0000 0000 0000 0000 0001 1010
// 二进制码11010 等于26
js

相同的两个值,按位异或比按位或得出的结果小 1

左移

<< 表示,二进制位向左移动的位数

let oldValue = 2; // 二进制表示 10
let newValue = oldValue << 5; // 二进制表示 1000000
console.log(newValue) // 十进制 64
js

2 的二进制 10,向左移 5,补了 5 个 0,1000000 即为 64。

但是左移会保留符号,-2 左移 5 得到 -64,并不是 64

有符号右移

>> 表示,与左移同理,也会保留符号。

let oldValue = 64; // 二进制表示 1000000
let newValue = oldValue >> 5; // 二进制表示 10
console.log(newValue) // 十进制 2
js

无符号右移

>>> 表示,

let oldValue = 64; // 二进制表示 1000000
let newValue = oldValue >>> 5; // 二进制表示 10
console.log(newValue) // 十进制 2

let oldValue = -64; // 二进制表示 11111111111111111111111111000000
let newValue = oldValue >>> 5; // 二进制表示 134217726
// 把符号位也当做值来位移了,导致结果相差很大
js

JavaScript 判断、循环语句

if

if( i > 1){
  alert("yes");
}else {
  alert ("no");
}
js

如果只有一条可以省略 {},但容易导致错误,应该避免

if( i > 1) alert("yes");
js

do-while

语句最少执行一次

var i = 0;
do {
  i += 2;
} while (i < 10);
js

while

var i = 0;
while ( i < 10){
  i += 2;
}
js

for

var a = 0;
for (var i = 0; a < 10; i++){
  a += 1;
}
js

for in

遍历数组/对象

var arr= ["Saab","Volvo","BMW"]

for (var x in arr){
  document.write(arr[x] + "<br />")
}
js

for of

let arr = [[1,2],['a','b']]
for (var [key, value] of arr) {
 console.log(key + "," + value);
}
// 1,2
// a,b
js
  • break;停止循环
  • continue;停止这次循环

with

  • 改变代码块的作用域,查找变量会先找 obj 里面的
  • 大量使用with会导致性能下降,不建议使用(因为修改了作用域链)
with(obj){
  // 代码块
}
js

switch

switch (i){
  case "0" :
	  alert('1') // i为0时
  	break; // 退出
    
  default: // 默认执行
	  alert('default') 
}
js

关键字与保留字

ECMA-262 第6 版规定的所有关键字如下:

break do in typeof case else instanceof var catch export new void class extends return while const finally super with continue for switch yield debugger function this default if throw delete import try

始终保留:enum

严格模式下保留:

implements package public interface protected static let private

模块代码中保留:await

这些词汇不能用作标识符,但现在还可以用作对象的属性名。一般来说最好不要用

评论
来发一针见血的评论吧!
表情

快来发表评论吧~

推荐文章
  • 测试文章

    20点赞10评论

  • webpack5(一)

    20点赞10评论