JavaScript
简介
JavsScript 于 1995 年由 Brendan Eich 用时 10 天写出,用于网景浏览器。最后的名字叫 LiveScript,也被局部员工称为 Mocha。那时 Java 语言很风行,出于商业化的考量,更名为 JavaScript,但两者之间没有关联。
最早的 JS 作为脚本语言给浏览器减少一些诸如鼠标追随等交互性特效,通过在 HTML 中增加 <script>
元素实现。
1996 年网景和 ECMA 达成了协定,起草 JS 的标准,第一版标准由 ECMA 做出并于 1997 释出。这个标准被称为 ECMA-262 规范。
JS 并不是一个独立的实体,它仅存在于实现中,这个实现称为 JS 引擎。
传统的 JS 引擎环境就是浏览器,确切来说,JS 引擎是浏览器的一个构建块。
此外,JS 引擎自身也能够和浏览器的其余局部交互,这些局部被称为浏览器 API。
所以 JS 代码有两个性能:
- 和浏览器中的 JS 引擎交互
- 和浏览器中的 JS 引擎外的其余局部交互
随后在 2009 年,Ryan Dahl 公布了 Node.js,他把 JS 引擎作为一个独立的实体,使得 JS 能够在浏览器外,作为服务端环境运行。
几种相似 JavaScript 的语言
- JScript
- VBScript
- TypeScript
为什么抉择 JavaScript
目前最风行的语言之一
- 浏览器惟一编程语言
- 使用者数量多
- 容易应用
无处不在
- 纯 JavaScript (Vanilla JS / Plain JS)
- UI 库/框架(React/Vue/Angular/jQuery/Ember/Next)
- 服务端(Node/Deno/Bun)
- 挪动端(React Native)
- 桌面端(Electron)
- 社区宏大
- 需要大
正文
被正文的代码块是不会执行的。
JavaScript有两种写正文(comment)的办法。
- 应用
//
正文掉以后行的代码。 这是一个行内正文:
// This is an in-line comment.
- 也能够应用多行正文,应用
/*
开始,*/
完结。 这是一个多行正文:
/* this is a multi-line commment */
最佳实际:应该增加正文来解释代码的作用,适当的正文能让代码更易懂。
分号
分号(semi-colon) ;
在 JavaScript 中用于示意一条语句的结尾。
console.log("hello world");console.log("hello world")
浏览器有主动插入分号(Automatic Semi-Colon Insertion / ASI)的性能,所以不加分号浏览器也能正确辨认语句的结尾。然而最佳实际显示,应该加上分号以进步代码的可读性。
变量 Variable
数据类型 Data Type
JavaScript 提供七种不同的根本类型(Primitive),别离是:
undefined
未定义、null
空、boolean
布尔、string
字符串、symbol
标记、number
数字、bigint
任意大的整数
根本类型不是对象(object),没有办法(method)和属性(property)。
申明 Declare
通过在变量后面应用关键字 var
,申明一个变量,例如:
var myName;//undefined
变量名称能够由数字、字母、美元符号 $
或者下划线 _
组成,然而不能蕴含空格或者以数字为结尾。
如果只申明不赋值,那么值为 undefined
。
字符串变量 String
"your name"
被称为字符串字面量(string literal)。 字符串文字或字符串是用单引号或双引号括起来的一系列零个或多个字符。
与其余一些编程语言不同的是,单引号和双引号的性能在 JavaScript 中是雷同的。
字符串在结尾和结尾都要有雷同的引号,如果在两头应用了雷同的引号,字符串会提前停止并抛出谬误。
'' // empty string"" // empty stringvar myFirstName = "Pete";var myLastName = "Mitchell";const conversation = 'Finn exclaims to Jake, "Algebraic!"';var str = 'de'f'; // SyntaxError: Unexpected identifier
可迭代
在 JS 中,字符串是可迭代(iterable)类型,指的是这种数据类型能够用循环迭代。
字符串也被称为类数组(array-like)类型。
字符串的长度 Length
通过 .length
来取得字符串的长度。
let lastNameLength = 0;const lastName = "Lovelace";lastNameLength = lastName.length;
字符串索引 Index
方括号表示法(Bracket notation)是一种在字符串中的特定 index(索引)处获取字符的办法。
大多数古代编程语言,是从 0 开始计数。 这被称为基于零(Zero-based)的索引。
let firstLetterOfLastName = "";const lastName = "Lovelace";firstLetterOfLastName = lastName[0]; // 'L'
字符串的不变性 Immutable
在 JavaScript 中,字符串(String
)的值是不可变的(immutable),这意味着一旦字符串被创立就不能被扭转。
例如:
let myStr = "Bob";myStr[0] = "J";
是不会把变量 myStr
的值扭转成 Job
的,因为变量 myStr
是不可变的。 留神,这并不 意味着 myStr
永远不能被扭转,只是字符串字面量 string literal 的各个字符不能被扭转。 扭转 myStr
的惟一办法是从新给它赋一个值,例如:
let myStr = "Bob";myStr = "Job";
字符串中的字符
为了读取从 0 开始某特定地位的字符,应用 charAt()
办法:
var greet = 'hello';greet.charAt(0) // h
字符串拼接
字符串拼接办法 concat()
:
"Wo".concat("rl").concat("d") # World
取得某字符的索引
应用 indexOf()
取得某字符在字符串中的索引地位,如果不蕴含该字符,则返回 -1
,如果蕴含多个雷同字符,则返回第一个字符呈现的地位;lastIndexOf()
返回雷同字符呈现的最初一个地位:
'greet'.indexOf('g') // 0'greet'.indexOf('e') // 2'greet'.indexOf('a') // -1'cace'.lastIndexOf('c'); // 2
Undefined & Null
undefined
数据类型只有一个值:undefined
。
- 所有函数默认返回
undefined
,除非显式返回一个值。 - 拜访对象不存在的属性,返回
undefined
- 已申明但未赋值的变量,
undefined
当 JavaScript 中的变量被申明的时候,程序外部会给它一个初始值 undefined
。 当对一个值为 undefined
的变量进行运算操作的时候,算进去的后果将会是 NaN
,它的意思是 "Not a Number"。 当用一个值是 undefined
的变量来做字符串拼接操作的时候,它会转换成字符串(string)undefined
。
null
指代短少(absence)值,undefined
指代未赋值。
var str = 'abc';str.match(/d/); // nullvar str2; // undefined
变量名辨别大小写 Case Sensitivity
最佳实际:应用驼峰命名法(camelCase)来命名一个 Javascript 变量。 在驼峰命名法中,变量名的第一个单词的首字母小写,前面的单词的第一个字母大写。
var someVariable;var anotherVariable;
var 和 let
应用 var
关键字(keywords)申明变量存在的问题:
- 在申明前就能够被应用
- 雷同的变量能够再次申明
- 能够在全局或者函数外部的作用域起作用
// 第一种console.log(user); // mikevar user = 'mike';// 第二种var camper = "James";var camper = "David";console.log(camper); // David
ES6 中引入了一个名为 let
的关键字,这是对 JavaScript 的一次重大更新,以解决与 var
关键字无关的潜在问题。
如果将下面代码中的 var
替换为 let
,则会导致谬误。应用 let
时,同名的变量只能申明一次。
const
const
具备 let
的所有性能,另外还有一个额定的益处,即应用 const
申明的变量是只读(Read-only)的。 它们是一个常量值(constant),这意味着一旦一个变量被赋值为 const
,它就不能被从新赋值:
const FAV_PET = 'cats';FAV_PETS = 'dogs'// this line will cause a error;
命名常量的常见做法是全副应用大写字母,单词之间用下划线分隔。
小数 Decimal
小数有时候也被称作浮点数或者 floats。
提醒: 不是所有的实数都能够用浮点数(floating point)来示意。 因为可能产生四舍五入的谬误。
var myDecimal = 5.7;
布尔值 Boolean
布尔值只能是两个值中的一个:true
或者 false
。
布尔值是不带引号的。 字符串 "true"
和 "false"
不是布尔值,在 JavaScript 中也没有非凡含意。
function welcomeToBooleans() { return true; }
真值 假值
真值(Truthy)和假值(Falsy)指的是在布尔值的上下文中,转换后为 true 和 false 的值。
所有除 false
、0
、-0
、0n
、""
、null
、undefined
和 NaN
以外的皆为真值)。
if (true)if ({})if ([])if (42)if ("0")if ("false")if (new Date())if (-42)if (12n)if (3.14)if (-3.14)if (Infinity)if (-Infinity)
JS 中有 8 个假值:
值 | 阐明 |
---|---|
false | false 关键字 |
0 | 数值 zero |
-0 | 数值 负 zero |
0n | 当 BigInt 作为布尔值应用时,听从其作为数值的规定. 0n 是 falsy 值。 |
"", '', `` | 这是一个空字符串 (字符串的长度为零). JavaScript 中的字符串可用双引号 "" , 单引号 '' , 或 模板字面量 ` ` 定义。 |
null | null - 短少值 |
undefined | undefined - 原始值 |
NaN | NaN - 非数值 |
BigInt Symbol
这两个数据类型是 ES6 引入的,BigInt 用于示意更大的数字,Symbol 用于示意对立标识符。
数字 Number
数字类型能够示意整数(integer) 或者小数(decimal)。
运算 Operation
赋值 Assignment
应用赋值(assignment)运算符 =
将值存储在变量中。
var myVariable = 5; // 间接赋值var myCode; // 先申明后赋值myCode = 100;
在赋值后,可应用赋值运算符将某变量的值赋给另一个变量。
var myVariable = 5;var b;b = myVariable;
加法 Add
var sum = 10 + 1; // sum = 11;
拼接 Concatenate
当 +
操作符被用于一个 String
类型的值的时候,它被称作拼接操作符。
const myStr = "This is the start." + " " + "This is the end."; // myStr "This is the start This is the end"
如果一个数字和字符串做拼接,JS 会把数字转化为字符串而后再拼接,最初失去一个字符串:
365 + " days" // "365 days"1 + "2" // "12"
这种看不见(under-the-hood)的转换称为“强制类型转换(coercion)”。
减法 Subtract
var difference = 10 - 2; // 8
乘法 Multiply
var product = 1 * 2; // 2
除法 Divide
var quotient = 10 / 2; // 5
自增 Increment
var my = 1;my++; // my 2
自减 Decrement
var my = 2;my--; // my 1
求余 Reminder
求余运算符(The modulus operator) %
返回两个数相除失去的余数
用法
在数学中,判断一个数是奇数还是偶数,只须要判断这个数除以 2
失去的余数是 0 还是 1。
提醒
余数运算符(remainder)有时被谬误地称为“模数”运算符。 它与模数十分类似,但不能用于正数的运算。
let remainder = 11 % 3; // 2
求幂 Exponentiation
求幂运算符 **
返回某底数的次幂
let exp = 10 ** 2 // 100
复合赋值 Compound Assignment
+=
,-=
,*=
,/=
`
+=
称为“addition assignment operator。
还能够应用 +=
运算符来拼接字符串到现有字符串变量的结尾。
let myVar = 1;myVar += 5;myVar -= 1;myVar *= 1;myVar /= 1;let myStr = "This is the first sentence.";myStr += " ";myStr += "This is the second sentence."
相等 Equality Operator
互相比拟的操作都返回一个 true
或 false
值。
最根本的运算符是相等运算符:==
。
在 JavaScript 中,为了让两个不同的数据类型(例如 numbers
和 strings
)的值能够作比拟,它必须把一种类型转换为另一种类型。 这叫作 “类型强制转换”。 转换之后,能够像上面这样来比拟:
1 == 1 //true1 == 2 //false1 == '1' //true"3" == 3 //true
严格相等 Strict Equality Operator
严格相等运算符不会做类型转换。如果比拟的值类型不同,那么在严格相等运算符比拟下它们是不相等的,会返回 false 。
3 === 3 //true3 === '3' //false
不等 Inquality Opeartor
不相等运算符(!=
)与相等运算符是相同的。 不相等运算符在比拟的时候也会转换值的数据类型。
1 != 2 // true1 != "1" // false1 != '1' // false1 != true // false0 != false // false
严格不等 Strict Inequality Operator
严格不相等运算符(!==
)与全等运算符是相同的。 严格不相等运算符不会转换值的数据类型。
3 !== 3 // false3 !== '3' // true;4 !== 3 // true;
大于 Greater Than Operator
应用大于运算符(>
)来比拟两个数字。 如果大于运算符右边的数字大于左边的数字,将会返回 true
。 否则,它返回 false
。
大于运算符在比拟的时候,会转换值的数据类型。
5 > 3 // true;7 > '3' // true;2 > 3 // false;'1' > 9 // false;
大于等于 Greater Than Or Equal To Operator
应用大于等于运算符(>=
)来比拟两个数字的大小。 如果大于等于运算符右边的数字比左边的数字大或者相等,会返回 true
。 否则,会返回 false
。
大于等于运算符在比拟的时候会转换值的数据类型。
6 >= 6 // true7 >= '3' // true2 >= 3 // false'7' >= 9 // false
小于 Less Than Operator
应用小于运算符(<
)来比拟两个数字。 如果小于运算符右边的数字比左边的数字小,它会返回 true
。 否则会返回 false
。 小于运算符在做比拟的时候会转换值的数据类型。
2 < 5 // true'3' < 7 // true5 < 5 // false3 < 2 // false'8' < 4 // false
小于等于 Less Than Or Equal To Operator
应用小于等于运算符(<=
)比拟两个数字的大小。 如果在小于等于运算符右边的数字小于或者等于左边的数字,它会返回 true
。 如果在小于等于运算符右边的数字大于左边的数字,它会返回 false
。小于或等于运算符会转换数据类型。
4 <= 5 // true'7' <= 7 // true5 <= 5 // true3 <= 2 // false'8' <= 4 // false
逻辑与 Logical And Opeator
当且仅当运算符的右边和左边都是 true,逻辑与运算符(&&
)才会返回 true
。
该运算符可用于两个比拟运算:
if (val <= 50 && val >= 25) { return "Yes"; }
逻辑或 Logical Or Operator
只有逻辑或运算符(||
)两边的任何一个运算的后果是 true
,则返回 true
。 否则,返回 false
。
if (val <= 10 || val >= 20) { return "Outside"; }
逻辑非 Logical Not Operator
当后果为 true
,逻辑非(!
)返回 false
;反之返回 true
。
var a = 6a > 5 # true!(a > 5) # false
三元运算符 Ternary Operator
条件运算符( conditional operator,)(也称为三元运算符( ternary operator))语法是:a ? b : c
, where a
是条件,当条件返回 true
的时候运行代码 b
,当条件返回 false
的时候运行代码 c
。
function checkEqual(a, b) { return a === b ? "Equal" : "Not Equal";}
确定类型 Typeof
应用 typeof
运算符确定变量或值的类型
typeof 3 // numbertypeof '3' // stringtypeof [] // objecttypeof {} // object
优先级和结合律
优先级(precedence)决定了运算的先后秩序,结合律(associativity)决定了在优先级雷同的状况下,运算的左右程序。
有两种结合律:
- 从左到右
- 从右到左
本义 Escape
定义一个字符串必须要用单引号或双引号来包裹它。 那么当字符串外面蕴含引号 "
或者 '
时,在 JavaScript 中,能够通过在引号后面应用反斜杠(\
)来本义引号。
const myStr = "I am a \"double quoted\" string inside \"double quotes\".";
转义字符 Escape Sequence
引号不是字符串中惟一能够被本义(escaped)的字符。 应用转义字符有两个起因:
- 首先是能够应用无奈输出的字符,例如退格。
- 其次是能够在一个字符串中示意多个引号,而不会出错。
代码 | 输入 |
---|---|
\' | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
\n | 换行符 |
\r | 回车符 |
\t | 制表符 |
\b | 退格 |
\f | 换页符 |
请留神,必须对反斜杠自身进行本义,它能力显示为反斜杠。
const myStr = "FirstLine\n\t\\SecondLine\nThirdLine";
条件 Conditional
条件语句也被称为控制流语句(flow control statement)。
if else
if
语句用于在代码中做出决定。
当条件的计算结果为 true
,程序执行大括号内的语句。 当布尔条件的计算结果为 false
,大括号内的代码将不会执行。应用 else
语句,能够执行当条件为假时相应的代码。
如果有多个条件语句,通过 else if
语句把 if
语句链起来。
function trueOrFalse(wasThatTrue) { if (wasThatTrue) { return "Yes, that was true"; } else { return "No, that was false"; }}
switch
switch
评估一个表达式,将表达式的值与 case 子句匹配。 从第一个匹配的 case
值执行语句,直到遇到 break
。
case
值应用严格相等(===
)运算符进行比拟。 留神 case
的值,1
匹配数字 1
,'1' 匹配字符串 '1'。break
通知 JavaScript 进行执行 switch 语句。 如果脱漏了 break
,下一个语句将会被执行。
在 switch
语句中,可能无奈用 case
枚举出所有可能的值。 相同,增加 default
语句,它会在找不到相匹配的 case
语句之后执行。 能够把它看作是 if/else
链中最初的那个 else
语句。
default
语句应该被放到最初。
function switchOfStuff(val) { let answer = ""; switch(val) { case 'a': answer = "apple"; break; case 'b': answer = "bird"; break; case 'c': answer = "cat"; break; default : answer = "stuff"; break; } return answer;}switchOfStuff(1); // stuff
如果想为 switch
中的多个不同的输出设置雷同的后果,能够这样写:
function sequentialSizes(val) { let answer = ""; switch(val) { case 1: case 2: case 3: answer = "Low"; break; case 4: case 5: case 6: answer = "Mid"; break; case 7: case 8: case 9: answer = "High";break; } return answer;}sequentialSizes(1); // Low
循环 Loop
while
当 while 指定的条件为真,循环才会执行,反之不执行。
const myArray = [];let i = 5;while (i <= 5 && i >= 0) { myArray.push(i); i--;}
下面的 i 称为计数器(counter)。
for
最常见的循环就是 for
,它能够循环指定次数。
for 循环中的可选三个表达式用分号隔开:
for (a; b; c)
,其中 a
为初始化语句,b
为条件语句,c
是最终的表达式。
初始化语句只会在执行循环开始之前执行一次。 它通常用于定义和设置循环变量。
循环条件语句会在每一轮循环的开始前执行,只有条件判断为 true
就会继续执行循环。 当条件为 false
的时候,循环将进行执行。 这意味着,如果条件在一开始就为 false,这个循环将不会执行。
终止循环表达式在每次循环迭代完结, 在下一个条件查看之前时执行,通常用来递增或递加循环计数。
const myArray = [];for (let i = 1; i <= 5; i++) { myArray.push(i);}
for-of
for-of
循环可用在可迭代对象中:
const colors = ['red', 'blue', 'yellow'];for (var color of colors) { console.log(color);}
do-while
它被称为 do...while
循环,是因为不论什么状况,它都会首先 do
(运行)循环里的第一局部代码,而后 while
(当)规定的条件被评估为 true
(真)的时候,它会持续运行循环。
const myArray = [];let i = 10;do { myArray.push(i); i++;} while (i < 11);
嵌套循环
如果有一个二维数组,能够应用雷同的逻辑,先遍历里面的数组,再遍历外面的子数组。
let myArray = [[1, 2], [3, 4]];for (let i = 0; i < myArray.length; i++) { for (let j = 0; j < myArray[i].length; j++) { console.log(myArray[i][j]); }}
函数 Function
把代码的重复部分抽取进去,放到一个函数 (function)中。
通过函数名加上前面的小括号来调用(invoke / call)这个函数,就像这样: functionName();
每次调用函数时,大括号之间的所有代码都将被执行。
function reusableFunction() { console.log("Hi World");}reusableFunction(); // Hi World
传参 Passing value with Argument
函数的参数 (parameters)在函数调用中充当传入函数的输出占位符(也叫形参)。 函数调用时,参数能够为一个或多个。 调用函数时输出(或传递 "passed")的理论值被称为参数(arguments)。
function functionWithArgs(a,b) { console.log(a + b);}functionWithArgs(3, 4); // 7
返回值 Return Value
应用 return
语句把数据从一个函数中传进去。
function timesFive(a) { return a * 5;}timesFive(1); // 5
在函数没有 return
语句的状况下,当调用它时,该函数会执行外部代码,返回的值是 undefined
。
let sum = 0;function addThree() { sum = sum + 3;}function addFive() { sum += 5;}addThree();addFive();
作用域和函数 Scope
全局作用域 Gobal Scope
在 JavaScript 中,作用域波及到变量的作用范畴。 在函数外定义的变量具备 全局 作用域。 具备全局作用域的变量能够在代码的任何中央被调用。
未应用 let
或 const
关键字申明的变量会在 global
范畴内主动创立。 当在代码其余中央无意间定义了一个变量,刚好变量名与全局变量雷同,这时会产生意想不到的结果。 应该总是用 let
或 const
申明变量。
部分作用域 Local Scope
在一个函数内申明的变量,以及该函数的参数都具备部分(local)作用域。 这意味着它们只在该函数内可见。
在 ES5 中,只有函数能创立部分作用域;ES6 中,应用 let
和 const
能够创立块级作用域(block scope),块级作用域是被申明变量所属的块,如果在函数外就是全局,如果函数内就是块级或者部分。
function test(a) { let a = 3; console.log(a);}// 3;console.log(a);// Reference Error;
优先级
一个程序中有可能具备雷同名称的局部变量和全局变量。 在这种状况下,局部变量将会优先于全局变量。
const outerWear = "T-Shirt";function myOutfit() { const outerWear = "sweater"; return outerWear;}myOutfit(); // sweater
数组 Array
在 JS 中,array 也是 object,有内置办法和属性。
应用数组(array
)存储多个数据。以左方括号开始定义一个数组,以右方括号完结,外面每个元素之间用逗号隔开。
const myArray = [0, 1, "code"];
多维数组 Multi-Dimensional Array
在其余数组中嵌套数组,这也叫做多维数组(multi-dimensional array)
const myArray = [["html","css"],"javascript"];
索引拜访 Index Access
应用索引(indexes)来拜访数组中的数据。数组索引与字符串一样应用方括号来示意,不同的是,它们不是指定字符,而是指定数组中的一个条目。 数组索引与字符串索引一样是从 0 开始(zero-based)的。留神:数组名与方括号之间不应该有任何空格,比方array [0]
。
const myArray = [50, 60, 70];var myData = myArray[0]; // 50
拜访嵌套数组
与拜访嵌套对象相似,数组的方括号能够用来对嵌套数组进行链式拜访。
const myPlants = [ { type: "flowers", list: [ "rose", "tulip", "dandelion" ] }, { type: "trees", list: [ "fir", "pine", "birch" ] }];const secondTree = myPlants[1].list[1]; // pine
索引批改 Index Modify
与字符串不同,数组的条目是 可变的 并且能够自在更改,即便数组是用 const
申明的。
const myArray = [18, 64, 99];myArray[0] = 45; // [45,64,99]
拜访多维数组
应用方括号表示法拜访数组时,第一个方括号拜访的是数组的最外层(第一层),第二个方括号拜访的是数组的第二层,以此类推。
const myArray = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], [[10, 11, 12], 13, 14],];const myData = myArray[2][1]; // 8;
push()
将数据增加到数组开端的简略办法是 push()
函数。
.push()
承受一个或多个参数(parameters),并把它压入到数组的开端。
const myArray = [["John", 23], ["cat", 2]];myArray.push(["dog", 3]); // [["John", 23], ["cat", 2],["dog", 3]]
pop()
.pop()
函数移除数组开端的元素并返回这个元素。
const myArray = [["John", 23], ["cat", 2]];let removedFromMyArray = myArray.pop(); // ["cat", 2]
shift()
shift()
移除的是第一个元素。
const myArray = [["John", 23], ["dog", 3]];const removedFromMyArray = myArray.shift(); // ["John", 23]
unshift()
unshift
(移入)一个元素到数组的头部。
const myArray = [["John", 23], ["dog", 3]];myArray.unshift(["Paul", 35]); // ["Paul", 35]],[["John", 23],["dog", 3]
splice()
splice()
能够从数组中的任意地位间断删除任意数量的元素。
splice()
最多能够承受 3 个参数。
splice()
接管的前两个参数是整数,示意正在调用的splice()
数组中的元素的索引或地位。 splice()
的第一个参数代表从数组中的哪个索引开始移除元素,而第二个参数示意要从数组中的这个地位开始删除多少个元素。
splice()
不仅会批改调用该办法的数组,还会返回一个蕴含被移除元素的数组:
const arr = [2, 4, 5, 1, 7, 5, 2, 1];arr.splice(1, 4);console.log(arr);
第三个参数能够是一个或多个元素,这些元素会被增加到数组中。 这样,可能便捷地将数组中的一个或多个间断元素换成其余的元素。
function htmlColorNames(arr) { arr.splice(0, 2, "DarkSalmon", "BlanchedAlmond"); return arr;}console.log(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurquoise', 'FireBrick']));
slice()
slice()
不会批改数组,而是会复制,或者说提取(extract)给定数量的元素到一个新数组。 slice()
只接管 2 个输出参数:第一个是开始提取元素的地位(索引),第二个是提取元素的完结地位(索引)。 提取的元素中不包含第二个参数所对应的元素。
function forecast(arr) { return arr.slice(2, 4);}console.log(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']));
开展运算符...
开展运算符复制数组
let thisArray = [true, true, undefined, false, null];let thatArray = [...thisArray];
开展运算符合并数组
开展语法(spread)的另一个重要用处是合并数组,或者将某个数组的所有元素插入到另一个数组的任意地位。
let thisArray = ['sage', 'rosemary', 'parsley', 'thyme'];let thatArray = ['basil', 'cilantro', ...thisArray, 'coriander'];
forEach
forEach
办法接管一个函数,该函数会在每一个数组项中执行。该函数的第一个参数是以后数组元素自身,第二个参数是索引(可选参数)。
const fruits = ['kiwi','mango','apple','pear'];function appendIndex(fruit,index) { console.log(`${index}.${fruit}`)}fruits.forEach(appendIndex);
通常会把 forEach
接管的函数体间接写入函数调用中:
const fruits = ['kiwi','mango','apple','pear'];fruits.forEach(function(fruit, index) { console.log(`${index}.${fruit}`)})
filter()
相似 forEach
,该办法用于每一个数组项,它会依据传入函数返回一个过滤后的数组:
const nums = [100,200,30,40,10,0];nums.filter(function (item) { return item > 100;})// [200]
map()
该办法依据传入的函数,把某数组的值依照函数规定映射(map)到另一数组:
[0,10,20,30].map(function (num) { return num ** 2;}) // [0, 100, 400, 900]
对象 Object
对象(object)实质上是键值对(key-value pair)的汇合。 或者说,一系列被映射到惟一标识符的数据就是对象;习惯上,惟一标识符叫做属性(property)或者键(key);数据叫做值(value)。
JS 中罕用对象字面量语法 {}
来创立一个对象。
var user = {};
也能够把属性和值以键值对的模式间接申明来创建对象:
const myDog = { "name": "Good", "legs": 4, "tails": 1, "friends": ["code", "fads"]};
对象和arrays
相似,区别在于数组应用索引来拜访和批改数据,而对象中数据是通过属性
拜访的。
对象非常适合用来存储结构化数据。属性都存储为字符串,也能够应用数字作为属性。甚至能够省略单字字符串属性中的引号。
然而,如果对象有非字符串属性的话,JavaScript 会主动将它们转为字符串。
in
JavaScript 提供了两种不同的形式来查看对象是否有某个属性: 一个是通过 hasOwnProperty()
办法,另一个是应用 in
关键字。
users.hasOwnProperty('Alan'); // true'Alan' in users; // true
for ... in 遍历对象
对象是不可迭代的,所以不能间接应用 for
和 for-of
循环。
const car = { speed: 100, color: 'blue'}for (prop of car) { console.log(prop);}// Uncaught TypeError: car is not iterable
遍历对象中的所有属性, 只须要应用 JavaScript 中的 for...in 语句即可。
for-in
对象遍历对象和其原型的属性;for-of
仅遍历对象本身的属性。
let car = { speed: 100, engine: 'true'}let car2 = Object.create(car);for (prop of car2) { console.log(prop); } // Uncaught TypeError: car2 is not iterablefor (prop in car2) { console.log(prop);} // color speed engine 程序不固定for (key of Object.keys(car2)) { console.log(key);} // color
留神:对象中的键是无序的,这与数组不同。 因而,一个对象中某个属性的地位,或者说它呈现的绝对程序,在援用或拜访该属性时是不确定的。
for (let user in users) { console.log(user);}
Object.keys()
给 Object.keys()
办法传入一个对象作为参数,来生成蕴含对象所有键的数组。 这会返回一个由对象中所有属性(字符串)组成的数组。 须要留神的是,数组中元素的程序是不确定的。
let users = { Alan: { age: 27, online: false }, Jeff: { age: 32, online: true }, Sarah: { age: 48, online: false }, Ryan: { age: 19, online: true }};function getArrayOfUsers(obj) { return Object.keys(obj);}console.log(getArrayOfUsers(users)); // [ 'Alan', 'Jeff', 'Sarah', 'Ryan' ]
遍历对象中的属性和值:
var clothingItem = { price: 50, color: 'beige', material: 'cotton', season: 'autumn'}for (key of Object.keys(clothingItem)) { console.log(keys, ":", clothingItem[key]);}
Object.values()
给 Object.values()
办法传入一个对象作为参数,来生成蕴含对象所有值的数组。 这会返回一个由对象中所有属性的值组成的数组。
const car3 = { speed: 300, color: 'yellow'}console.log(Object.values(car3)); // [300,'yellow']
Object.entries()
给 Object.entries()
办法传入一个对象作为参数,来生成蕴含对象所有键值对的数组。
const car4 = { speed: 400, color: 'magenta'}console.log(Object.entries(car4)); // [ ['speed', 400], ['color', 'magenta'] ]
拜访属性 Access Property
拜访对象属性有两种形式:点号表示法(.
)和方括号表示法([]
)
点号拜访 Dot Notation
如果提前晓得要拜访的属性名,应用点号表示法是最不便的。
const testObj = { "hat": "ballcap", "shirt": "jersey", "shoes": "cleats"};const hatValue = testObj.hat; // ballcapconst shirtValue = testObj.shirt; // jersey
方括号拜访 Bracket Notation
拜访对象属性的第二种形式是方括号表示法([]
)。这种办法须要把属性作为字符串写入方括号内。如果要拜访的属性名中蕴含空格,就必须应用方括号表示法来获取它的属性值。
const testObj = { "an entree": "hamburger", "my side": "veggies", "the drink": "water"};const entreeValue = testObj["an entree"];const drinkValue = testObj["the drink"];
最初,方括号拜访比点号拜访的劣势是:能够计算表达式。
var arrOfKeys = ['speed', 'altitude', 'color'];var drone = { speed: 100, altitude: 200, color: 'red'}for (var i = 0; i < arrOfKeys.length; i++) { console.log(drone[arrOfkeys[i]]);}/*100200red*/
变量拜访
还能够拜访对象上作为变量值存储的属性。 当须要遍历对象的所有属性,或者依据一个变量的值查找对应的属性值时,这种写法尤其实用。
const dogs = { Fido: "Mutt", Hunter: "Doberman", Snoopie: "Beagle"};const myDog = "Hunter";const myBreed = dogs[myDog];console.log(myBreed); // Doberman
应用这一概念的另一种状况是:属性的名字是在程序运行期间动静收集失去的。
const someObj = { propName: "John"};function propPrefix(str) { const s = "prop"; return s + str;}const someProp = propPrefix("Name");console.log(someObj[someProp]);
留神,当应用变量名拜访属性时,没有 应用引号包裹它,因为应用的是变量的值,而不是变量的名字。
const testObj = { 12: "Namath", 16: "Montana", 19: "Unitas"};const playerNumber = 16;const player = testObj[playerNumber]; // Montana
嵌套拜访
通过间断应用点号表示法和方括号表示法来拜访对象的嵌套属性。
const myStorage = { "car": { "inside": { "glove box": "maps", "passenger seat": "crumbs" }, "outside": { "trunk": "jack" } }};const gloveBoxContents = myStorage.car.inside["glove box"]; // maps
更改属性 Update
创立了 JavaScript 对象后,能够随时更新它的属性。 应用点或中括号操作符来更新。
const myDog = { "name": "Coder", "legs": 4, "tails": 1, "friends": ["freeCodeCamp Campers"]};myDog["name"] = "Happy Coder";
增加属性 Add
应用点号来更新,给 JavaScript 对象增加属性。
能够给对象增加多种数据类型的属性,包含函数;如果增加了函数属性,就称为“办法”。
const myDog = { "name": "Happy Coder", "legs": 4, "tails": 1, "friends": ["freeCodeCamp Campers"]};myDog.bark = "woof";myDog.call = function() { console.log('hello');}
删除属性 Delete
能够应用 delete
删除对象的属性
const myDog = { "name": "Happy Coder", "legs": 4, "tails": 1, "friends": ["freeCodeCamp Campers"], "bark": "woof"};delete myDog.tails;
查看对象属性 Test
用对象的 .hasOwnProperty(propname)
办法来查看对象是否有指定的属性。 .hasOwnProperty()
找到该属性时返回 true
,找不到该属性时返回 false
。
obj.hasOwnProperty(check);
简单对象 Complex Object
提醒:数组中有多个 JSON 对象的时候,对象与对象之间要用逗号隔开。
const myMusic = [ { "artist": "Billy Joel", "title": "Piano Man", "release_year": 1973, "formats": [ "CD", "8T", "LP" ], "gold": true }, { "artist": "Mitchell", "title": "Cocomo", "release_year": 1900, "formats": [ "fds", "Fsdf" ] }];
递归 Recursion
递归是函数调用本身的操作。
function sum(arr, n) { if (n <= 0) return 0; else return sum(arr, n - 1) + arr[n-1];}
Math 库
罕用的常量
- PI 值:
Math.PI
- 欧拉数 Euler 常量:
Math.E
- 2 的自然对数:
Math.LN2
舍入办法
Math.ceil()
无论小数局部如何,向上舍入到最靠近的整数Math.floor()
无论小数局部如何,向下舍去到最靠近的整数Math.round()
如果小数局部大于.5
,向上舍入到最靠近的整数 ,否则向下舍去最靠近整数Math.trunc()
去掉小数局部,仅留下整数局部
console.log(Math.ceil(2.3)); // 3console.log(Math.ceil(2.7)); // 3console.log(Math.floor(2.3)); // 2console.log(Math.floor(2.7)); // 2console.log(Math.round(2.3)); // 2console.log(Math.round(2.7)); // 3console.log(Math.trunc(2.3)); // 2console.log(Math.trunc(2.7)); // 2
随机分数 Random
随机数非常适合用来创立随机行为。
在 JavaScript 中,能够用 Math.random()
生成一个在0
(包含 0)到 1
(不包含 1)之间的随机小数。
function randomFraction() { return Math.random();}
随机整数
- 用
Math.random()
生成一个随机小数。 - 把这个随机小数乘以
20
。 - 用
Math.floor()
向下取整,取得它最近的整数。
记住 Math.random()
永远不会返回 1
。同时因为是在向下取整,所以最终取得的后果不可能有 20
。 这确保了咱们取得了一个在 0
到 19
之间的整数。
function randomWholeNum() { return Math.floor(Math.random() * 10);}
生成某个范畴内的数字
须要定义一个最小值 min
和一个最大值 max
。
function randomRange(myMin, myMax) { return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;}
parseInt
parseInt()
函数解析一个字符串返回一个整数。
如果字符串中的第一个字符不能转换为数字,则返回 NaN
。
function convertToInteger(str) { return parseInt(str);}convertToInteger("56");
它还能够传入第二个参数,指定了字符串中数字的基数。 基数能够是 2 到 36 之间的整数。
parseInt(string, radix);function convertToInteger(str) { return parseInt(str, 2);}convertToInteger("10011");
数学计算办法 Arithmetic and calculus
- 幂运算:
Math.pow()
- 开算术平方根:
Math.sqrt()
- 开立方根:
Math.cbrt()
- 取绝对值:
Math.abs()
- 取对数:
Math.log()
Math.log2()
Math.log10()
- 取最值:
Math.min()
Math.max()
- 三角(Trigonometric)计算:
Math.sin()
Math.cos()
Math.tan()
Math.pow(2,3)8Math.sqrt(4)2Math.cbrt(8)2Math.abs(-2)2Math.log(4)1.3862943611198906Math.log2(4)2Math.log10(100)2Math.log(2.7)0.9932517730102834Math.sin(4/5)0.7173560908995228Math.cos(4/5)0.6967067093471654Math.tan(4/5)1.0296385570503641