任何语言的外围所形容的都是这门语言在最根本的层面上如何工作,波及语法、操作符、数据类型以及内置性能,在此基础之上才能够构建简单的解决方案。
语法
-
辨别大小写
例如let Main="这是一个主体" let main=""
-
标识符
什么是标识符:
变量、函数、属性或函数参数的名称,
规定:
第一个字符必须是一个字母、下划线(_)或美元符号($),剩下的其余字符能够是字母、下划线、美元符号或数字。
举荐应用形式
采纳驼峰式命名即第一单词首字母小写其余单词首字母大小
例如:let userName="admin"
-
正文
单行和多行// 这是单行正文 /* 多行正文 1.xxxx 2.xxxxx */
-
严格模式
"use strict" // 如果放在脚本结尾整个脚本采纳严格模式 // 如果放在函数体内则该函数采纳严格模式
-
语句
1.ECMAScript 中的语句以分号结尾
2. 多条语句能够合并到一个 C 语言格调的代码块中(一条语句也举荐放在代码块中)。关键字和保留字
关键字和保留字没什么好说的,以下这些词汇不能用作标识符来应用。
//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
变量
- 什么是变量
用于保留任何类型的数据,申明变量的的形式有 var、let、const 三种
var 申明特色 -
函数作用域
function fn(){console.log(a)//undefined var a=123 console.log(a)//123 } fn() console.log(a)// 报错 Uncaught ReferenceError: a is not defined // 比照 if(true){var a=123} console.log(a)//123
-
变量晋升
console.log(a)//undefined var a=123 console.log(a)//123
let 申明
-
块级作用域
function fn(){console.log(a)//undefined let a=123 console.log(a)//123 } fn() console.log(a)// 报错 Uncaught ReferenceError: a is not defined // 比照 if(true){let a=123} console.log(a)// 报错 Uncaught ReferenceError: a is not defined
-
暂时性死区
console.log(a)//Uncaught ReferenceError: Cannot access 'a' before initialization let a=12
-
同一作用域下不能申明冗余
let a=12 let a=123//Uncaught SyntaxError: Identifier 'a' has already been declared 或 var a=121//Uncaught SyntaxError: Identifier 'a' has already been declared 或 const a//Uncaught SyntaxError: Identifier 'a' has already been declared
const 申明
const 的行为与 let 基本相同,惟一一个重要的区别是用它申明变量时必须同时初始化变量,且尝试批改 const 申明的变量会导致运行时谬误
数据类型
原始类型:Undefined、Null、String、Boolean、Number、Symbol 和、Bigint
援用类型:Object
检测数据类型的办法
-
typeof
console.log(typeof "str")//string console.log(typeof 12)//number console.log(typeof true)//boolean console.log(typeof undefined)//undefined console.log(typeof Symbol("id"))//symbol console.log(typeof 10n)//bigint console.log(typeof null)//object console.log(typeof {})//object console.log(typeof function(){})//function console.log(typeof [])//object
typeof 对于根本数据类型除去 null 判断为 object 其余都能精确判断出,对于援用类型数据可能判断出对象和函数
-
instanceof 检测援用类型
console.log({} instanceof Object)//ture console.log([] instanceof Array)//ture console.log(function(){} instanceof Function)//ture console.log(new Date() instanceof Date)//ture
-
toString 比拟全面的检测类型的办法
let toString=Object.prototype.toString console.log(toString.call(null))//[object Null] console.log(toString.call(undefined))//[object Undefined] console.log(toString.call('1212'))//[object String] console.log(toString.call(1212))//[object Number] console.log(toString.call(true))//[object Boolean] console.log(toString.call(Symbol('ID')))//[object Symbol] console.log(toString.call(10n))//[object BigInt] console.log(toString.call({}))//[object Object] console.log(toString.call([]))//[object Array] console.log(toString.call(new Date()))//[object Date] console.log(toString.call(function (){}))//[object Function] console.log(toString.call(NaN))//[object Number] console.log(toString.call(Infinity))//[object Number]
Undefined
用于未定义的值 —— 只有一个 undefined 值的独立类型
Null
用于未知的值 —— 只有一个 null 值的独立类型
Boolean
用于 true 和 false。
类型转换数据类型 转换成 true 的值 转换成 false 的值 Boolean true fasle String 非空字符串 “”(空字符串) Number 非零数值(包含无穷值) 0、NaN Object 任意对象 null Undefined N/A(不存在) undefined Number
用于任何类型的数字:整数或浮点数,在 ±(2^53^-1) 范畴内的整数, 非凡的值 Infinity、-Infinity 和 NaN。
数值转换方法: - Number()// 转型函数,可用于任何数据类型
转换规则:
1. 布尔值,true 转换为 1,false 转换为 0。
2. 数值,间接返回
3.null,返回 0
4.undefined,返回 NaN。
5. 字符串:
01. 字符串蕴含数值字符,包含数值字符后面带加、减号的状况,则转换为一个十进制数值(疏忽后面的 0)
02. 字符串蕴含无效的浮点值格局,则会转换为相应的浮点值(疏忽后面的 0)
03. 无效的十六进制格局,则会转换为与该十六进制值对应的十进制整
数值
04. 空字符串(不蕴含字符),则返回 0
05. 蕴含除上述情况之外的其余字符,则返回 NaN
6. 对象:
调用 valueOf()办法,并依照上述规定转换返回的值。如果转换后果是 NaN,则调用 toString()办法,再依照转换字符串的规定转换 - parseInt()// 须要失去整数时能够优先应用能够指定进制数。字符串最后面的空格会被疏忽,遇到小数点不在解析,倡议应用此办法时指定进制数
- parseFloat()// 与 parseInt()相似,不能指定进制数,遇到第二个小数点不在解析,始终疏忽字符串结尾的零,只解析十进制值
String
用于字符串:一个字符串能够蕴含 0 个或多个字符,所以没有独自的单字符类型。
字符串标示:”、””、“ - 字符字面量
字面量 | 含意 |
---|---|
\n | 换行 |
\t | 制表 |
\b | 退格 |
\r | 回车 |
\f | 换页 |
\ \ | 反斜杠(\) |
\ ‘ | 单引号(’),在字符串以单引号标示时应用,例如 ’He said, \’hey.\” |
\ “ | 双引号(”),在字符串以双引号标示时应用,例如 ”He said, \”hey.\”” |
\ ` | 反引号,在字符串以反引号标示时应用,例如He said, \ hey.\“ |
\xnn | 以十六进制编码 nn 示意的字符(其中 n 是十六进制数字 0~F),例如 \x41 等于 ”A” |
\unnnn | 以十六进制编码 nnnn 示意的 Unicode 字符(其中 n 是十六进制数字 0~F),例如 \u03a3 等于希腊字符 ”Σ |
-
转换为字符串办法
xxx.toString(number)//2、8、10、16 示意进制书或者不加参数转字符串
-
模板字面量(“)
//1. 能够换行例子:let str=` 我是一个,字符串。` // 字符串插值例子:let age=20 let man=` 我是一个男人,年龄 ${age}岁 `
Symbol
用于惟一的标识符
1. 根本应用办法let name=Symbol("ID"); console.log(name.description)//ID //Symbol()函数不能与 new 关键字一起作为构造函数应用,能够通过 Object 实现 {let sym=new Symbol("ID");// TypeError: Symbol is not a constructor } {let sym =Symbol() let mySymbol =Object(sym) console.log(typeof myWrappedSymbol); // "object" } // 警示!Symbol 不会被主动转换为字符串
2. 应用全局符号注册表
// 创立全局符号 let s = Symbol.for('foo'); let s4=Symbol.for('foo'); console.log(s === s4)//true console.log(Symbol.keyFor(s)); // foo // 创立一般符号 let s2 = Symbol('bar'); let s3=Symbol('bar'); console.log(s2===s3)//false console.log(Symbol.keyFor(s2)); // undefined
3. 应用符号作为属性
let s1=Symbol('id'); let obj={ name:"lly", [s1]:'01', [Symbol('value')]:'我是一名程序员' } //Symbol 在 for…in 中会被跳过 for(let key in obj){console.log(key)//name }
4. 罕用内置符号
// 全局函数 Symbol 的一般字符串属性,指向一个符号的实例。所有内置符号属性都是不可写、不可枚举、不可配置的。@@iterator=>Symbol.iterator
5.Symbol.asyncIterator
指定了一个对象的默认异步迭代器const myAsyncIterable = new Object(); myAsyncIterable[Symbol.asyncIterator] = async function*() { yield "hello"; yield "async"; yield "iteration!"; }; (async () => {for await (const x of myAsyncIterable) {console.log(x); // expected output: // "hello" // "async" // "iteration!" } })();
6.Symbol.hasInstance
// 用于判断某对象是否为某结构器的实例 // 实现一个自定义的 instanceof 行为 class MyArray {static [Symbol.hasInstance](instance) {return Array.isArray(instance); } } console.log([] instanceof MyArray); // true
7.Symbol.isConcatSpreadable
// 管制数组或相似数组(array-like)的对象的行为: //1. 对于数组对象,用于 concat 时,能够扭转其默认状况下。let alpha = ['a', 'b', 'c'], numeric = [1, 2, 3]; let alphaNumeric = alpha.concat(numeric); console.log(alphaNumeric); // 后果: ['a', 'b', 'c', 1, 2, 3] numeric[Symbol.isConcatSpreadable] = false; console.log(alphaNumeric); // 后果: ['a', 'b', 'c',[ 1, 2, 3]] //2. 对于相似数组的对象,用于 concat 时,该对象整体作为新数组的元素, 扭转默认行为 var x = [1, 2, 3]; var fakeArray = {[Symbol.isConcatSpreadable]: true,// 如果 false length: 2, 0: "hello", 1: "world" } //[Symbol.isConcatSpreadable]: true x.concat(fakeArray); // [1, 2, 3, "hello", "world"] //[Symbol.isConcatSpreadable]: false x.concat(fakeArray);// [1, 2, 3, {…}]
8.Symbol.iterator
//Symbol.iterator 为每一个对象定义了默认的迭代器。该迭代器能够被 for...of 循环应用。let myIterable = {} myIterable[Symbol.iterator] = function* () { yield 1; yield 2; yield 3; }; [...myIterable] // [1, 2, 3]
9.Symbol.match
// 指定了匹配的是正则表达式而不是字符串 // 禁止表达式检测 let re = /foo/; re[Symbol.match] = false; "/foo/".startsWith(re); // true "/baz/".endsWith(re); // false
10.Symbol.replace
// 当一个字符串替换所匹配字符串时所调用的办法 class Replace1 {constructor(value) {this.value = value;} [Symbol.replace](string) {return `s/${string}/${this.value}/g`; } } console.log('foo'.replace(new Replace1('bar'))); // expected output: "s/foo/bar/g"
11.Symbol.search
// 指定了一个搜寻办法,这个办法承受用户输出的正则表达式,返回该正则表达式在字符串中匹配到的下标 class caseInsensitiveSearch {constructor(value) {this.value = value.toLowerCase(); } [Symbol.search](string) {return string.toLowerCase().indexOf(this.value); } } console.log('foobar'.search(new caseInsensitiveSearch('BaR'))); // expected output: 3
12.Symbol.species
// 被构造函数用以创立派生对象 class MyArray extends Array { // 笼罩 species 到父级的 Array 构造函数上 static get [Symbol.species]() { return Array;} } var a = new MyArray(1,2,3); var mapped = a.map(x => x * x); console.log(mapped instanceof MyArray); // false console.log(mapped instanceof Array); // true
13.Symbol.split
// 正则表达式的索引处宰割字符串的办法 let exp = { pat:'in', [Symbol.split](str) {return str.split(this.pat); } } console.log("dayinlove".split(exp));//["day", "love"]
14.Symbol.toPrimitive
// 烦扰一个对象转换为原始值时输入的后果的 var obj2 = {[Symbol.toPrimitive](hint) {if (hint == "number") {return 10;} if (hint == "string") {return "hello";} return true; } }; console.log(+obj2); // 10 -- hint 参数值是 "number" console.log(`${obj2}`); // "hello" -- hint 参数值是 "string" console.log(obj2 + ""); //"true"-- hint 参数值是"default"
15.Symbol.toStringTag
// 自定义类型标签 class ValidatorClass {get [Symbol.toStringTag]() {return "Validator";} } console.log(Object.prototype.toString.call(new ValidatorClass())); // "[object Validator]"
Symbol 的应用场景
- ‘ 暗藏 ’ 对象属性
- JavaScript 应用了许多零碎 Symbol,这些 Symbol 能够作为 Symbol.* 拜访
Bigint
用于任意长度的整数。
// 用法
let bg=1n
或
let big=BigInt(1)
Object
用于更简单的数据结构(一组数据和性能的汇合)
Object 类型的所有办法和属性:
1.constructor// 用于创立以后对象的函数。
2.hasOwnProperty(propertyName)// 判断以后对象实例(不是原型)上是否存在给定的属性
3.isPrototypeOf(object)// 判断以后对象是否为另一个对象的原型
4.propertyIsEnumerable(propertyName)// 用于判断给定的属性是否能够应用
5.toLocaleString()// 对象的字符串示意,该字符串反映对象所在的本地化执行环境
6.toString()// 对象的字符串
7.valueOf()// 对象对应的字符串、数值或布尔值示意
操作符
一元操作符
-
递增 | 递加(++ | –)
// 前缀和后缀区别 // 后缀版递增和递加在语句被求值后才产生 let num=10 console.log(num--)//10 或 console.log(--num)//9 // 递增和递加操作符遵循如下规定 /*1. 对于字符串,如果是无效的数值模式,则转换为数值再利用扭转。变量类型从字符串变成数值。2. 对于字符串,如果不是无效的数值模式,则将变量的值设置为 NaN。变量类型从字符串变成 数值。3. 对于布尔值,如果是 false,则转换为 0 再利用扭转。变量类型从布尔值变成数值。4. 对于布尔值,如果是 true,则转换为 1 再利用扭转。变量类型从布尔值变成数值。5. 对于浮点值,加 1 或减 1。6. 如果是对象,则调用其(第 5 章会具体介绍的)valueOf()办法获得能够操作的值。对失去的 值利用上述规定。如果是 NaN,则调用 toString()并再次利用其余规定。变量类型从对象变成数值。*/
-
一元加 | 减(+|-)
// 一元加和减操作符次要用于根本的算术,但也能够像下面的例子那样,用于数据类型转换。
位操作符
-
按位非(~)
// 对数值取反并减 1 let num=10 console.log(~num)//-11
- 按位与(&)
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
- 按位或(|)
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
- 按位异或(^)
第一个数值的位 | 第二个数值的位 | 结 果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
-
左移(<<)
依照指定的位数将数值的所有位向左挪动用 0 补全let oldValue = 2; console.log(oldValue.toString(2))// 等于二进制 10 let newValue = oldValue << 5; console.log(newValue.toString(2))// 等于二进制 1000000
-
有符号右移(>>)
let oldValue = 64; console.log(oldValue.toString(2))// 等于二进制 1000000 let newValue = oldValue >> 5; console.log(newValue.toString(2))// 等于二进制 10
-
无符号右移(>>>)
// 对于负数,无符号右移与有符号右移后果雷同。let oldValue = 64; console.log(oldValue.toString(2))// 等于二进制 1000000 let newValue = oldValue >>> 5; console.log(newValue.toString(2))// 等于二进制 10 // 无符号右移操作符将正数的二进制示意当成负数的二进制示意来解决。因为正数是其绝对值的二补数,所以右移之后后果变得十分之大 let oldValue = -64; console.log(oldValue.toString(2))// 等于二进制 -1000000 let newValue = oldValue >>> 5; console.log(newValue.toString(2))// 等于二进制 111111111111111111111111110 console.log(newValue.toString(10))// 等于十进制 134217726
布尔操作符
- 逻辑非(!)
1. 如果操作数是对象,则返回 false。
2. 如果操作数是空字符串,则返回 true。
3. 如果操作数是非空字符串,则返回 false。
4. 如果操作数是数值 0,则返回 true。
5. 如果操作数是非 0 数值(包含 Infinity),则返回 false。
6. 如果操作数是 null,则返回 true。
7. 如果操作数是 NaN,则返回 true。
8. 如果操作数是 undefined,则返回 true。
!!=>Boolean() - 逻辑与(&&)
第一个操作数 | 第二个操作数 | 结 果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
- 逻辑或(||)
第一个操作数 | 第二个操作数 | 结 果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
乘性操作符
- 乘法(*)
- 除法(/)
- 取余(%)
指数操作符
- 指数 (2**3=>2^3^)
加性操作符
- 加法(+)
- 减法(-)
关系操作符
- 小于(<)
- 大于(>)
- 小于等于(<=)
- 大于等于(>=)
相等操作符
- ==// 等于
任一操作数是布尔转成数值再比拟
一个操作数是字符串一个是数值转成数字在比拟
一个对象另一个不是调用 valueOf()获得原生值在比拟
null 和 undefined 相等。
null 和 undefined 不能转换为其余类型的值再进行比拟
任一操作数是 NaN,则相等操作符返回 false,NaN 和 NaN 不相等
两个操作数都是对象,则比拟它们是不是同一个对象,是 true 否 false
表达式 | 结 果 |
---|---|
null == undefined | true |
“NaN” == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | true |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
“5” == 5 | true |
-
===// 全等
不进行类型转换,未转换前相等是 true 否则 false
条件操作符// 三目运算符 条件? 执行体 1: 执行体 2 等价于 if(){}else{}
赋值操作符
- 乘后赋值(*=)
- 除后赋值(/=)
- 取模后赋值(%=)
- 加后赋值(+=)
- 减后赋值(-=)
- 左移后赋值(<<=)
- 右移后赋值(>>=)
- 无符号右移后赋值(>>>=)
逗号操作符
// 一条语句中执行多个操作
let a=1,b=2,c=3;
或
let A=(1,2,3,0)//0
语句
if 语句
// 流程管制
if(// 条件 1){// 执行体 1}else if(// 条件 2){// 执行体 2}else{// 执行体 3}
do-while 语句
// 后测试循环语句
let i = 0; // 循环初始值
do {
i += 2; // 循环规定
console.log(i)//2 执行此语句
} while (i < 0);// 循环阀值
while 语句
// 先测试循环语句
let i = 0; // 循环初始值
while(i < 0) { // 循环阀值
i += 2;// 循环规定
console.log(i)// 不执行此语句
}
for 语句
// 先测试循环语句, 把初始值和执行的表达式加进来
for(let i=0;i<10;i++){// 初始值,阈值,循环表达式
// 执行语句
}
for-in 语句
// 一种严格的迭代语句,用于枚举对象中的非符号键属性,null 和 undefined,则不执行循环体。for(let key in enumObject){//enumObject 可枚举对象
console.log(key)
}
for-of 语句
// 一种严格的迭代语句,用于遍历可迭代对象的元素
for(let key of enumObject){//enumObject 遍历可迭代对象
console.log(key)
}
标签语句
// 用于循环嵌套
start:for(let i=0;i<10;i++){if(i%5==0){break start//1,2,3,4,5}
}
break 和 continue 语句
//break 立刻退出循环,强制执行循环后的下一条语句
// 例:let num=0;
for(let i=1;i<10;i++){if(i%3==0){break;}
num++
}
console.log(num)//2
//continue 立刻退出循环,但会再次从循环顶部开始执行
// 例:let num=0;
for(let i=1;i<10;i++){if(i%3==0){continue;}
num++
}
console.log(num)//6
with 语句
// 严格模式不容许应用 with 语句,否则会抛出谬误(不举荐应用)
// 将代码作用域设置为特定的对象
// 应用场景针对一个对象重复操作,这时候将代码作用域设置为该对象能提供便当
// 例子
let qs = location.search.substring(1);
let hostName = location.hostname;
let url = location.href;
// 下面代码中的每一行都用到了 location 对象。如果应用 with 语句,就能够少写一些代码:with(location) {let qs = search.substring(1);
let hostName = hostname;
let url = href;
}
switch 语句
// 管制语句
switch(expression){// 参数
case value1: // 条件 1
statement // 执行语句
break;
case value2: // 条件 1
statement // 执行语句
break;
.....
default:
statement// 执行语句
}
函数
严格模式对函数的一些限度:
- 函数不能以 eval 或 arguments 作为名称;
- 函数的参数不能叫 eval 或 arguments;
- 两个命名参数不能领有同一个名称。