# JavaScript 学习

# HTML 中的 JavaScript

# <script> 元素

<script> 元素中的代码或外部 JavaScript 文件被解释完之前,页面的其余内容不会被加载,也不会被显示;

如果同时存在 <script> 元素中的代码和外部 JavaScript 文件时,浏览器只会下载并执行脚本文件,忽略行内代码;

现代 Web 应用程序一般将 JavaScript 的引用放在 <body> 元素中的页面内容后面;

# 延迟脚本

defer 属性:表明脚本在执行时不会影响页面的构造,即脚本会被延迟到整个页面都解析完毕后再运行;

# 输入输出

# 输出

<script>
        prompt('这是一个输入框');
        alert('这是一个警示框');
        console.log('这是控制台打印输出的')
    </script>

# 输入

var age = promopt('请输入你的年龄');

# 语言基础

# 数据类型

# typeof 操作符

# Number 型

数字型进制:

数值型范围:

数值型的三个特殊值:

isNaN()函数:

NaN:

浮点数:

永远不要测试某个特定的浮点数值;

字符串数组转数字数组

let strArr=['1','2','3']
let newArr=strArr.map(Number)

# String 型

单引号或者双引号,如果嵌套就外双内单或内双外单;

字符串转义符:

字符串长度:

var txt ='abcdefg';
console.log(txt.length);

字符串拼接:

toString():

数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString () 方法,该方法返回字符串的一个副本)都有 toString () 方法。但 null 和 undefined 值没有这个方法;

# Boolean 型

true 和 false 是区分大小写的,故必须小写;

# undefined 与 null

如果一个变量声明未赋值,就是 undefined(未定义数据类型);

一个声明变量给 null 值,里面存的值为空;逻辑上讲,null 值表示一个空对象指针;

let car =null;
console.log(typeof car); //"object"

# Symbol 型

symbol 的值是通过 Symbol () 函数生成,每一个 symbol 的值都是唯一的,并且 symbol 类型的值可以作为对象的属性标识符使用,这也是 symbol 类型设计的目的。
所以现在对象属性名可以为两种类型:一种就是原本的字符串类型,一种即为新增的 symbol 类型。凡是使用 symbol 命名的属性都是独一无二的,保证不与其他属性名产生冲突。

# Object 型

对象(Object)其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建 的对象类型的名称来创建。而创建 Object 类型的实例并为其添加属性和(或)方法,就可以创建自定义对象;

# 数值转换

常见的类型转换有:

  • 强制转换(显示转换)
  • 自动转换(隐式转换)

显示转换:

Number():

Number(324) // 324
// 字符串:如果可以被解析为数值,则转换为相应的数值
Number('324') // 324
// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc') // NaN
// 空字符串转为 0
Number('') // 0
// 布尔值:true 转成 1,false 转成 0
Number(true) // 1
Number(false) // 0
//undefined:转成 NaN
Number(undefined) // NaN
//null:转成 0
Number(null) // 0
// 对象:通常转换成 NaN (除了只包含单个数值的数组)
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5

Number 转换的时候是很严格的,只要有一个字符无法转成数值,整个字符串就会被转为 NaN

parseInt()

parseInt 相比 Number ,就没那么严格了, parseInt 函数逐个解析字符,遇到不能转换的字符就停下来;

parseInt('32a3') //32

不能转换出小数;

parseFloat():

String()

// 数值:转为相应的字符串
String(1) // "1"
// 字符串:转换后还是原来的值
String("a") // "a"
// 布尔值:true 转为字符串 "true",false 转为字符串 "false"
String(true) // "true"
//undefined:转为字符串 "undefined"
String(undefined) // "undefined"
//null:转为字符串 "null"
String(null) // "null"
// 对象
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"

Boolean()

可以将任意类型的值转为布尔值,转换规则如下:

Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean(NaN) // false
Boolean('') // false
Boolean({}) // true
Boolean([]) // true
Boolean(new Boolean(false)) // true

隐式转换:

我们这里可以归纳为两种情况发生隐式转换的场景:

  • 比较运算( ==!=>< )、 ifwhile 需要布尔值地方
  • 算术运算( +-*/%

# 字符串操作方法

提取字符串:

slice() substr() substring()

查看字符串位置:

indexOf lastIndexOf()

trim():

这个方法会创建字符串的一个副本,删除前、后所有空格符,再返回结果;另外,trimLeft () 和 trimRight () 方法分别用于从字符串开始和末尾清理空格符。

repeat():

这个方法接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果。

padStart () 与 padEnd ():

大小写转换:

toLowerCase toUpperCase

将字符串全部转换为小写(大写);

字符串替换:

replace()

localeCompare():

# Math

Math 的基本属性:

求最大最小值:

min() max()

舍入方法:

round() fround() ceil() floor()

round(): 执行四舍五入;

fround (): 返回数值最接近的单精度(32 位)浮点值;

ceil (): 向上舍入最接近的整数;

floor(): 向下舍入最接近的整数;

随机数:

random()

该方法生成一个在 [0,1) 范围内的随机数;

通常使用方法:

function selectFrom(lowerValue,upperValue){
    let choices = upperValue-lowerValue+1;
    return Math.floor(Math.random()*choices+lowerValue);
}

其它数学方法:

# Array

from()

Array.from () 的第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个 length 属性和可索引元素的结构;

Array.from () 还接收第二个可选的映射函数参数,这个函数可以直接增强新数组的值;

fill()

copyWithin()

toString()

push()

该方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度

pop()

该方法则用于删除数组的最后一项,同时减少数组的 length 值,返回被删除的项

shift()

该方法它会删除数组的第一项并返回它,然后数组长度减 1。

unshift()

该方法会在数组开头添加任意多个值,然后返回新的数组长度

reverse()

该方法将数组元素反向排序;

sort()

一般使用该方法时接收一个比较函数;

slice()

如果参数有负数,则改为数组长度加上负值。

splice()

定型数组:

# Map

写法关键字描述
new Map()创建创建 map
map.set(key, value)设置根据键存储值
map.get(key)获取根据键来返回值,如果 map 中不存在对应的 key ,则返回 undefined
map.has(key)是否存在如果 key 存在则返回 true ,否则返回 false
map.delete(key)删除删除指定键的值
map.clear()清空清空 map
map.size大小返回当前元素个数

ObjectsMaps 类似的是,它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值。

对比:

意外的键

  • Map:不包含任何键( Map默认情况不包含任何键。只包含显式插入的键。
  • Object:有一个原型( 一个 Object有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

键的类型

  • Map:任意值( 一个 Map的键可以是任意值,包括函数、对象或任意基本类型。
  • Object:必须是 String 或 Symbol( 一个Object 的键必须是一个 String 或是Symbol。

键的顺序

  • Map:有序( Map 中的 key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。
  • Object:无序( 一个 Object 的键是无序的

Size

  • Map:可直接获取长度( Map 的键值对个数可以轻易地通过size 属性获取
  • Object:不能直接获取长度( Object 的键值对个数只能手动计算

性能

  • Map:在频繁增删键值对的场景下表现更好。
  • Object:在频繁添加和删除键值对的场景下未作出优化。

# Set

​ Set 与数组类似, Set 集合中的元素不重复。

  • 查找元素: 在数组中使用 indexOf () 或 includes () 检查元素是否存在比较慢;
  • 删除元素: 在 Set 中,可以通过值删除元素。即在数组中,基于索引的 splice () 功能;
  • 插入元素: 在 Set 中添加元素比在数组中通过 push ()、 unshift () 或其他同类操作要快;
  • 去重: Set 对象仅能存储不同的值;

Set 常用操作方法:

方法 / 属性功能介绍
size获取当前 Set 对象的长度
add(value)向当前 Set 对象中添加一个值,返回的是 Set 对象,所以支持链式写法
delete(value)删除当前 Set 对象中的一个值,返回一个布尔值,表示是否删除成功
has(value)检测这个 value 是否是当前 Set 对象的一个元素,通过返回的布尔值表示
clear()清除当前 Set 对象所有元素,没有返回值

Set 遍历方法:

方法 / 属性功能介绍
keys()返回该 Set 对象键名的遍历器,等同 values ()
values()返回该 Set 对象键值的遍历器,等同 keys ()
entries()返回该 Set 对象键值对的遍历器 (目前感觉没什么用)
forEach()使用回调函数遍历该 Set 对象的每个元素

# 字符串数组方法

# 数组

改变原数组的方法:

# push

​ push () 方法可向数组的末尾添加一个或多个元素,并返回新的长度

let ary=[10,20,30,40]
let res=ary.push(50)
//ary=[10,20,30,40,50]
//res=5

# unshift

​ unshift () 方法可向数组的开头添加一个或更多元素,并返回新的长度

let ary=[10,20,30,40]
let res=ary.unshift(50)
//ary=[50,10,20,30,40]
//res=5

# pop

​ pop () 用于删除并返回最后一个元素,尾部删除,返回被删除的元素,改变原数组;

var a = [1,2,3]
var b = a.pop()
 
console.log(a) // [1,2]
console.log(b) // 3

# shift

​ shift () 用于删除并返回首个元素,删除首部元素,返回被删元素,改变原数组;

var a = [1,2,3]
var b = a.shift()
 
console.log(a) // [2,3]
console.log(b) // 1

# sort

按 ascii 码排序,改变原数组,返回排序后的数组;也可以接收一个比较函数;

var a = ['a','b','d','c']
 
console.log(a.sort())  // ['a','b','c','d']
console.log(a)  // ['a','b','c','d']

# splice

​ splice () 方法用于添加或删除数组中的元素;

var n =array.splice(index,howmany,item1,.....,itemX)
// 如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组,如果只增加了元素,则返回空数组
参数描述
index必需。规定从何处添加 / 删除元素。 该参数是开始插入和(或)删除的数组元素的下标,必须是数字。
howmany可选。规定应该删除多少元素。必须是数字,但可以是 "0"。 如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。
item1, ..., itemX可选。要添加到数组的新元素

# reverse

reverse () 方法用于颠倒数组中元素的顺序,返回的是颠倒后的数组,会改变原数组

var a  = [1,3,2,7,6]
 
console.log(a.reverse())  // [6,7,2,3,1]
console.log(a)  // [6,7,2,3,1]

# fill

fill () 方法用于将一个固定值替换数组的元素,返回改变后的原数组

array.fill('value', start, end)
//start 与 end 为可选参数

不改变原数组的方法:

# forEach

遍历整个数组,中途不能中断,没有返回值,不能改变原数组

var arr = ['a','b','c']
var copy = []
arr.forEach(function(item){
     copy.push(item)   
})
console.log(copy)

# slice

​ slice (startIndex,endIndex) 返回从 startIndex 开始 (包括),到 endIndex (不包括) 之间的原属组成的数组,返回新数组,不改变原数组

var a = [1,2,3]
var b = a.slice(0,1)
// 不填参数则表示剪切整个数组  
var c = a.slice() 
console.log(a) // [1,2,3] 
console.log(b) // [1]
console.log(c) // [1,2,3]    
console.log(a===c)  //false// 注意 a !== c 
 
// 负数表示从后往前数
var d = a.slice(-1,-2)   
console.log(d) // []   从左向右截取,所以说为 []
 
var e = a.slice(-1)  
console.log(e)  // [3]

# join

join () 方法用来将数组转换为字符串,不改变原数组,返回转换后的字符串

var a = [1,2,3,4,5]
 
console.log(a.join(','))  // 1,2,3,4,5
console.log(a)  // [1,2,3,4,5]

# filter

filter () 方法返回数组中满足条件的元素组成的新数组,原数组不变,参数为一个方法, filter() 把传入的函数依次作用于每个元素,然后根据返回值是 true 还是 false 决定保留还是丢弃该元素;

var a = [1,2,3,4,11]
// 第一个参数为一个方法,有三个参数,current: 当前值 index: 当前值下标 array: 这个数组对象
var b = a.filter(function(current,index,array){
    return current < 10
})
 
console.log(b) // [1,2,3,4]
console.log(a) // [1,2,3,4,11]

# map

map () 方法来根据需求格式化原数组,返回格式化后的数组。原数组不变;

var a = [1,2,3,4,5]
// 参数同 filter 方法
var b = a.map(function(current,index,array){
    return current + 1
})
 
console.log(b) // [2,3,4,5,6]
console.log(a) // [1,2,3,4,5]

# indexOf 和 lastIndexOf

indexOf (某元素,startIndex) 从 startIndex 开始,查找某元素在数组中的位置,若存在,则返回第一个位置的下标,否则返回 - 1

lastIndexOf (某元素,startIndex) 和 indexOf () 相同,区别在于从尾部向首部查询

不会改变原数组,返回找到的 index, 否则返回 - 1

若不使用下标,则一般通过 includes () 方法代替 indexOf ()

var a = [1,2,4,3,4,5]
 
console.log(a.indexOf(4))  // 2
console.log(a.indexOf(4,3)) // 4

# includes

includes () 方法,返回一个布尔值。 参数是一个 value, 一般用于简单数组。

对于复杂数组,则可以使用 some () 方法替代 includes () 方法;

var a = [1,2,3]
console.log(a.includes(1))  // true

# concat

首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组,不会影响原始数组;

let colors = ["red", "green", "blue"];
let colors2 = colors.concat("yellow", ["black", "brown"]);
console.log(colors); // ["red", "green","blue"]
console.log(colors2); // ["red", "green", "blue", "yellow", "black", "brown"]

# every

对数组的每一项都运行给定的函数,若每一项都返回 ture, 则返回 true;

var a = [1,2,3,4,5]
 
var b = a.every(function(current,index,array){
       return current < 6
})
 
var c = a.every(function(current,index,array){
       return current < 3
})
console.log(b)  // true 
console.log(c)  // false

# some

对数组的每一项都运行给定的函数,若存在一项或多项返回 ture, 则返回 true;

var a = [1,2,3,4,5]
 
var b = a.some(function(current,index,array){
       return current > 4
})
 
var c = a.some(function(current,index,array){
       return current > 5
})
console.log(b)  // true 
console.log(c)  // false

# find

找到数组中第一次满足条件的元素,并返回改元素,若找不到则返回 undefined。不改变原数组。

和 filter () 方法的区别在于:filter 返回值是所有满足条件的元素组成的数组,

一般在需要使用找到的元素时,用 find () 方法

var a = [1,2,3,4]
//b 在下面需要使用,则一般用 find
var b = a.find(function(ele,index,array){
    return ele == 1
})
 
var c = 3
var d = b + c
console.log(a) // [1,2,3,4]
console.log(b) // 1
console.log(d) // 4
 
// 若只需判断元素是否存在
// 若果是简单数组 (非对象数组),则一般使用 Array.includes (value) 方法
// 如果为对象数组,则可以使用 Array.some () 方法
 
var a = [1,2,3]
console.log(a.includes(1))  // true
 
var a = [{"name": "xiaoming" },{"name": "xiaohong"}]
 
console.log(a.some(function(ele){
    return ele.name == 'xiaoming'
}))                            // true

# findIndex

findIndex () 的作用同 indexOf (),返回第一个满足条件的下标,并停止寻找。

区别是 findIndex () 的参数为一个回调函数,且一般用于对象数组

var a = [1,2,3,4]
 
var b = a.findIndex(function(ele,index,array){
    return ele === 2
})
 
var c = a.indexOf(2)  
 
console.log(a)  // [1,2,3,4]
console.log(b)  // 1
console.log(c)  // 1

# Array.from

该 Array.from () 方法将从具有 length 属性或可迭代对象的任何 JavaScript 对象中返回一个数组对象。

// 可用来创建多维数组
let ary= Array.from(Array(m),()=>Array(n).fill(0))
// 创建 m*n 的全 0 数组

# isArray

用来判断一个元素是否为数组;

Array.isArray([])  // true
Array.isArray({})  // false

# 字符串

# concat

concat () 方法用于连接两个或多个字符串或。

该方法没有改变原有字符串,但是会返回连接两个或多个字符串的新字符串

var str1="Hello ";
var str2="world!";
var str3=" Have a nice day!";
var n = str1.concat(str2,str3);
// n='Hello world! Have a nice day!'

# slice、substr、substring

不改变原字符串,返回新字符串

# trim

trim()移除字符串前后的空格,经常在对 input 和 textarea 的值做判断时用到,不改变原字符串,返回新字符串;同理:trimLeft () trimRight ()

# toLowerCase

把字符串转换成小写的;

# toUpperCase

把字符串转换成大写的;

# repeat

接收一个整数参数,表示要将字符串复制多少次,然后返回拼接所有副本后的结果;

let stringValue = "na ";
let copyResult = stringValue.repeat(2) // na na

# charAt

返回指定索引的字符;

var str = "abbcalgldkjgldgehlgjldf"
str.charAt(1) // 结果是 b

# includes

从字符串中搜索传入的字符串,并返回一个表示是否包含的布尔值;

let message = "foobarbaz";
console.log(message.includes("bar")); // true
console.log(message.includes("qux")); // false

# indexOf

同上

# split

把字符串分割为子字符串数组,并返回新数组

var ary=string.split(separator,limit)
// 第一个参数为用于分割的字符串,一般为 '' 或 ' '
// 第二个参数为返回的字符串的最大长度
var str="How are you doing today?";
var n=str.split("");
//['H', 'o', 'w', ' ', 'a', 'r', 'e', ' ', 'y', 'o', 'u', ' ', 'd', 'o', 'i', 'n', 'g', ' ', 't', 'o', 'd', 'a', 'y', '?']

# match

match () 方法可在字符串内检索指定的值,找到一个或多个正则表达式的匹配,并返回一个新数组;

let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = text.match(pattern);
console.log(matches[0]); // "cat"
// 参数 regexp 规定要匹配的模式的 RegExp 对象。如果该参数不是 RegExp 对象,则需要首先把它传递给 RegExp 构造函数,将其转换为 RegExp 对象

# replace

replace () 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串;

let stringNew=stringOld.replace(regexp/substr,replacement)
let text = "cat, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos); // 1

​ search () 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。找到则返回匹配索引,否则返回 -1;

stringObject.search(regexp)
//stringObject 中第一个与 regexp 相匹配的子串的起始位置。
let text = "cat, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos); // 1

# 正则表达式

模式

  • g:全局模式,常用于执行一个全局搜索匹配,即(不仅仅返回第一个匹配的,而是返回全部);
  • i:不区分大小写;
  • m:执行一个多行匹配

普通字符

  • \w :匹配一个字母、数字、下划线;
  • \W :匹配一个非字母、数字、下划线;
  • \d :匹配一个数字
  • \D :匹配一个非数字
  • \n :查找一个换行符
  • \r :查找一个回车符
  • \s :可以匹配一个空格(也包括 Tab 等空白符);
  • [A-Z] :[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母;
  • [A-z] :查找从大写 A 到小写 z 范围内的字符,即所有大小写的字母;
  • [0-9] :查找从 0 至 9 范围内的数字,即查找数字;
  • [a-zA-Z0-9] :查找所有的英文字符和数字;

特殊字符

  • [^] :查找不在方括号内任意一个字符(如 [^ABC] );
  • . :可以匹配任意字符,但不包括换行符,故 'py.' 可以匹配 'pyc''pyo''py!' 等等;
  • ?n? 匹配任何包含零个或一个 n 的字符串;
  • *n* 匹配任何包含零个或多个 n 的字符串;
  • +n+ 匹配任何包含一个及以上 n 的字符串;
  • {}n{x} 匹配包含 x 个 n 的序列的字符串, n{x,y} 匹配包含最少 x 个、最多 y 个 n 的序列的字符串, n{x,} 匹配包含至少 x 个 n 的序列的字符串;
  • | :表示在两个子模式的匹配结果中任选一个,如 /a {dog|cat}/ ;
  • () :表示括号内的字符必须全部包含;
  • [] :表示方括号内的字符为指定字符的范围;
  • ^ :匹配开头,在多行检测中,会匹配(限制)一行的开头,如 /^\w+/ 会匹配第一个单词;
  • $ :匹配结尾,在多行检测中,会匹配一行的结尾,如 /\w+$/ 会匹配最后一个单词;
  • \ :转义字符,用于匹配一些保留的字符 [ ] ( ) { } . * + ? ^ $ \ |
  • \num :反向引用,所谓的 \1 引用了第一个 () 匹配到的内容,比如 (x)(y)\2 该正则是想匹配到第一个字符是 x, 第二个字符是 y,第三个字符也是 y 的内容,即 xyy 能够被匹配到,但是 xya、xyb 就不能被匹配到;

# test()

test () 方法用于检测一个字符串是否匹配某个模式,如果字符串 string 中含有与 RegExpObject 匹配的文本,则返回 true,否则返回 false。

RegExpObject.test(string)

代码实例:

let data = ['#123456', '247146086@qq.com', '15281091015', '123.0.5.255',
    'https://www.bilibili.com/video/BV1QK4y1K72U?spm_id_from=333.999.0.0',
    '247146086', '0.0.0.0', '#ABC', '2021-10-01', '18215576625', '825662107', '15281091015',
    'https://www.https://nc3021.github.io/', '255.255.255.255', '1257730824',
    '#9bf', '1984-02-30']
function regexp(ary, reg) {
    let result = []
    ary.forEach(element => {
        if (element.match(reg))
            result.push(element.match(reg)[0])
    })
    return result
}
//phoneNumber
let regPhone = /^1[3-9][0-9]{9}$/g
let aryPhone = regexp(data, regPhone)
console.log('phoneNumber:', aryPhone)
//QQNumber
let regQQ = /^[1-9][0-9]{4,9}$/
let aryQQ = regexp(data, regQQ)
console.log('QQNumber:', aryQQ)
//color
let regColor = /^#([0-9a-fA-F]{6}$|[0-9a-fA-F]{3}$)/g
let aryColor = regexp(data, regColor)
console.log('Color:', aryColor)
//email
let regEmail = /^([\w\.\-]+)@([\w\.\-]+)\.([a-zA-Z]{2,6})$/g
let aryEmail = regexp(data, regEmail)
console.log('Email:', aryEmail)
//url
let regUrl = /^((https?|ftp|file):\/\/)?([\da-z\.\-]+)\.([a-z\.]{2,6})((.*\/)*)?(.*)?$/g
let aryUrl = regexp(data, regUrl)
console.log('Url:', aryUrl)
//Ipv4
let regIpv4 = /^(([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/g
let aryIpv4 = regexp(data, regIpv4)
console.log('Ipv4:', aryIpv4)
// 或 | 之间不用加(),原因不清
//date
let regDate = /^\d{4}-(0\d|1[012])-(0\d|[12]\d|3[01])/g
let aryDate = regexp(data, regDate)
console.log('Date:', aryDate)
var pattern1 = /\[bc\]at/;  
// 等价于 var pattern1 = new RegExp ("\\[bc\\] at", "i");

# 操作符

# 一元操作符

递增递减操作符(++/--):

前缀递增或递减时,变量的值都是在语句被求值以前改变的;后缀递增或递减时,变量的值都是在语句求值之后才改变的;

正负操作符(+/-):

# 位操作符

# 布尔操作符

逻辑非!:

通过使用(!!n)将一个值转换位其对应的布尔值;

逻辑与 &&:

逻辑或 ||:

一些特殊用法:

  • 防止初始值为 null(importent)

# 乘性操作符

乘法:

除法:

取模:

# 指数操作符(**)

# 加性操作符

加法:

减法:

# 关系运算符(><)

# 相等操作符

由于相等和不相等操作符存在类型转换问题,而为了保持代码中数据类型的完整性,一般推荐使用全等和不全等操作符;

# 迭代器

# 对象与类

# 对象

# 对象属性

数据属性:

将属性显式添加到对象之后,[[Configurable]]、[[Enumerable]] 和 [[Writable]] 都会被设置为 true,而 [[Value]] 特性会被设置为指定的值;

属性修改

Object.defineProperty () 方法:

在调用 Object.defineProperty () 时,configurable、enumerable 和 writable 的值如果不指定,则都默认为 false;

访问器属性:

属性定义

Object.defineProperty () 方法:

定义多个属性

Objext.define-Properties () 方法:

读取属性的特性:

Object.getOwnPropertyDescriptor () 方法:

合并对象:~P210

对象标识及相等判定:

对象结构:~P216

# 创建对象

工厂模式(非构造函数):

构造函数模式:

两者区别:

  • 没有显式地创建对象

  • 属性和方法直接赋值给了 this

  • 没有 return

    按照惯例,构造函数名称的首字母都是要大写的, 非构造函数则以小写字母开头;

    构造函数与普通函数唯一的区别就是调用方式不同。除此之外,构造函数也是函数。并没有把某个函数定义为构造函数的特殊语法。任何函数只要使用 new 操作符调用就是构造函数,而不使用 new 操作符调用的函数就是普通函数;

    但通过构造函数创建出的每个实例的函数虽然同名但不相等,故因此一般将函数定义转移到构造函数外部;

原型模式:

Object.getProtorypeOf () 方法:

返回参数的内部特性 Prototype 的值;

Object.create () 方法:

创建一个新对象,同时为其指定原型;

Object.hasOwnProperty () 方法:

确定某个属性是在实例上还是原型对象上;参数为属性名,返回 ture 则说明来自实例,返回 false 则说明来自原型;

in 操作符:

确定某个属性是否在该对象的实例或原型对象上;

Object.keys () 方法:

这个方法接收一个对象作为参数,返回包含该对象所有可枚举属性名称的字符串数组;

对象迭代:

Object.entries () 方法:

接收一个对象,返回它们内容(键值对)的数组;

Object.values () 方法:

接收一个对象,返回它们对象值的数组;

例:[[' 键 ',' 值 '],[' 键 ',' 值 '],[' 键 ',' 值 ']]

注意:非字符串属性会被转换为字符串输出,符号属性会被忽略;

# this

1:this 永远指向一个对象;

2:this 的指向完全取决于函数调用的位置

# 继承

原型链:

instanceof 操作符:

如果一个实例的原型链中出现过相应的构造函数,则返回 true;

console.log(instance instanceof Object);//ture

isProtorypeOf () 方法:

如果原型链中包含这个原型,则返回 true;

console.log(Object.prototype.isPrototypeOf(instance));//true
# 组合继承

​ 综合了原型链和盗用构造函数,通过盗用构造函数继承构造函数的属性,通过原型链继承原型上的方法;

​ 从而避免了原型中所包含的引用值会在所有的实例间共享的问题(原型链的弊端);以及盗用构造函数中重新定义方法的问题;

# 原型式继承

Object.create () 方法:

接收两个参数:第一个作为新对象原型的对象,第二个为给新对象定义额外属性的对象(可选)。在只有一个参数时, Object.create () 与这里的 object () 方法效果相同;

# 寄生式组合继承

​ 寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本。说到底就是使用寄生式继承来继承父类原型,然后将返回的新对象赋值给子类原型;

相比于组合继承,少调用了一次父构造函数(只在最后构造实例时调用了父构造函数),从而效率更高,是引用类型继承的最佳模式;

#

​ 与函数类型相似,定义类也有两种主要方式:类声明和类表达式。这两种方式都使用 class 关键字加大括号:

class Person {}// 类声明
const Animal = class {};// 类表达式

​ 与函数表达式式类似,类表达式在它们被求值前也不能引用。不过,与函数定义不同的是,虽然函数声明可以提升,但类定义不能;

类构造函数

​ constructor () 用于在类定义块内部创建类的构造函数。方法名 constructor 会告诉解释器在使用 new 操作符创建类的新实例时,应该调用这个函数。构造函数的定义不是必需的,不定义构造函数相当于将构造函数定义为空函数;

实例、原型、类成员:~P254

继承:~P258

# 代理和反射

# 函数

​ 函数声明可以提升,但函数表达式不可以;

# 函数参数

​ 函数的参数在函数内部表现为一个数组,存放在一个类数组对象 arguments 中;

​ 可以通过 arguments [0] 获得第一个参数;也可以通过 arguments 的 length 属性检查传入的参数个数,即

但如果采用箭头函数则没有 arguments 对象。

​ arguments 还有一个属性 callee , 是一个指向 arguments 对象所在函数的指针,可以让函数逻辑与函数名解耦;

function jiecheng(num){
    if (num<=1){
        return 1;
    }else{
        return num*jiecheng(num-1);
    }
}

# 期约与异步函数

Promise 详解与实现(Promise/A + 规范) - 简书 (jianshu.com)

async 函数执行返回一个 promise 对象,且 async 函数内部的返回值会当作这个 promise 对象 resolve 状态的值;

await 是一个表达式,如果后面不是一个 promise 对象,就直接返回对应的值,如果跟一个 promise 对象,await 将等待这个 promise 对象的 resolve 状态的值,且将这个值返回给前面的变量;

# 期约

~P325

# 异步函数

~P348

# 执行上下文

[深入理解 JavaScript 执行上下文和执行栈 - Fundebug - 博客园 (cnblogs.com)](https://www.cnblogs.com/fundebug/p/understand-javascript-context-and-stack.html#:~:text = 一、执行上下文(Execution Context). 1. 什么是执行上下文。简而言之,执行上下文就是当前 JavaScript 代码被解析和执行时所在环境的抽象概念,,JavaScript 中运行任何的代码都是在执行上下文中运行. 2. 执行上下文的类型。执行上下文总共有三种类型:. 全局执行上下文: 这是默认的、最基础的执行上下文。. 不在任何函数中的代码都位于全局执行上下文中。.)

# AJAX

​ AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。而传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。

  1. 创建 XMLHttpRequest 对象

    var xmlhttp;
    if (window.XMLHttpRequest)
    {
        //  IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
        xmlhttp=new XMLHttpRequest();
    }
    else
    {
        // IE6, IE5 浏览器执行代码
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    }
  2. 向服务器发送请求

    xmlhttp.open("GET","ajax_info.txt",true);
    xmlhttp.send();

  3. 服务器相应

    document.getElementById("myDiv").innerHTML=xmlhttp.responseText;

  4. onreadystatechange 事件

    xmlhttp.onreadystatechange=function()
    {
        if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
            document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
        }
    }

# BOM

浏览器对象模型(Browser Object Model)

# window

# Global 作用域

  • 通过 var 声明的所有全局变量和函数都会变成 window 对象的属性和方法;但通过 let 或 const 声明的则不会把变量添加给全局对象。
  • 直接访问未声明的变量会抛出异常,但通过 window 对象进行访问,可以判断未声明的变量是否存在。
alert(window.a) //undefined
alert(a)  // 抛出异常

# 打开和关闭窗口

​ window 对象提供了 window.open () 方法和 window.close () 方法分别用于打开窗口和关闭窗口,使用 window.open () 方法即可打开一个新的窗口,并可以设置新窗口的 URL 、标题以及大小属性,window.open () 的基本语法为:

window.open (URL , 窗口名字,特征,是否替换);
第一个参数为新打开窗口的 URl 地址,如果为空,则打开页面为白板;
第二个参数为打开窗口的名字(如果参数指定一个已经存在的窗口,那么该方法不再创建一个新窗口,而是对该指定窗口的引用;
第三个参数为新窗口显示标准浏览器的特征,详情如下表
第四个参数代表着指定的 URL 是否取代浏览器记录中的当前加载页面,true 为替换浏览器记录中的当前加载页面,false 为创建浏览器历史记录中的创建新的页面;

属性值描述
height窗口的高度,单位为像素,最小值为 100
left该窗口的左侧位置,单位为像素
location是否显示浏览器的地址栏。默认值为 yes
memubar是否显示浏览器的菜单栏。默认值为 yes
resizable是否可以改变浏览器窗口的大小。默认值为 yes
scrollbars是否显示浏览器的滚动条。默认值为 yes
status是否显示浏览器的状态栏。默认值为 yes
titlebar是否显示浏览器的标题栏。默认值为 yes
top窗口顶部的位置,单位为像素
width窗口的宽度,单位为像素,最小值为 100
<h1>父窗口</h1>
<button onclick="    
                 subWin = window.open('subWindow.html','子窗口','width=500','height=500','top=100','left=100');    
                 ">打开子窗口</button>
<button onclick="    
                 if (subWin!=null && !subWin.closed) {//存在且不是关闭状态 
                 subWin.close();    
                 }     
                 ">关闭子窗口</button>
<script>
  var subWin = null;// 定义子窗口    
</script>

# 窗口位置与窗口大小

window.screenLeft : 窗口相对于屏幕左侧的距离(单位:CSS 像素)

window.screenTop : 窗口相对于屏幕顶部的距离(单位:CSS 像素)

​ 所有现代浏览器都支持 4 个属性: innerWidthinnerHeightouterWidthouterHeight

outerWidthouterHeight 返回浏览器窗口自身的大小(不管是在最外层 window 上使用,还是在窗格中使用;

innerWidthinnerHeight 返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)。

# 定时器

setTimeout() 该方法通常接收两个参数:要执行的代码和在执行回调函数前等待的时间(毫秒)。第一个参数可以是包含 JavaScript 代码的字符串(类似于传给 eval () 的字符串)或者一个函数,第二个参数是要等待的毫秒数,并会返回一个唯一标识符,可用于取消该任务,只要是在指定时间到达之前调用 clearTimeout (),就可以取消超时任务。

let timeoutId =setTimeout(()=>alert('hello'),1000);
clearTimeout(timeoutId);// 取消超时任务

​ 因为 setTimeout() 只能执行一次,所以如果要反复执行该方法中包含的代码,则应该在该方法中包含对自身的调用:

var t = 0;
var i = 1;
function f() {
  var out = setTimeout(
    function () {
      t = i++;
      f();
    }, 1000
  );
  if (i > 3) {
    clearTimeout(out);
    alert('10s done')
  }
}
f();

setInterval() 与 setTimeout () 的使用方法类似,只不过指定的任务会每隔指定时间就执行一次,直到取消循环定时或者页面卸载。setInterval () 同样可以接收两个参数:要执行的代码(字符串或函数),以及把下一次执行定时代码的任务添加到队列要等待的时间。其也会返回一个标识符,通过 clearInterval () 来取消任务。

# 系统对话框

​ 可以让浏览器调用系统对话框向用户显示消息。这 些对话框与浏览器中显示的网页无关,而且也不包含 HTML。它们的外观由操作系统或者浏览器决定,无法使用 CSS 设置。此外,这些对话框都是同步的模态对话框,即在它们显示的时候,代码会停止执行, 在它们消失以后,代码才会恢复执行.

alert() : 只接收一个参数

confirm() :只接收一个参数,并返回布尔值

prompt() :接收两个参数,第一个是要显示给用户的文本,第二个是文本框的默认值(可以是空字符串),最后返回文本框中的值

<script>
        prompt('这是一个输入框');
        alert('这是一个警示框');
        console.log('这是控制台打印输出的')
  		var age = promopt('请输入你的年龄');
</script>

# location

​ location 是最有用的 BOM 对象之一,提供了当前窗口中加载文档的信息,以及通常的导航功能(URL)。 这个对象独特的地方在于,它既是 window 的属性,也是 document 的属性。也就是说, window.location 和 document.location 指向同一个对象。

location 对象的属性都是可读可写的,如果改变了相关属性值,浏览器就会载入新的页面。

navigator 对象包含了浏览器的基本信息,如名称、版本和系统等。

# screen

screen 对象存储客户端屏幕的信息。

# history

history 对象存储浏览器窗口的浏览历史。

go() 方法可以在用户历史记录中沿任何方向导航,可以前进也可以后退。这个方法只接收一个参数, 这个参数可以是一个整数,表示前进或后退多少步。

history.go(-1);// 后退一页
history.go(2);// 前进两页

history.length 用来表示历史记录的数量。

​ 对于窗口或标签页中加载的第一个页面,history.length 等于 1。 通过以下方法测试这个值,可以确定用户浏览器的起点是不是你的页面。

# DOM

文档对象模型(Document Object Model)

HTML DOM 定义了所有 HTML 元素的对象属性,以及访问它们的方法

换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准。

# DOM 属性

innerHTML 用于获取 HTML 元素的内容

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
 
<p id="intro">Hello World!</p>
 
<script>
var txt=document.getElementById("intro").innerHTML;
document.write(txt);
</script>
 
</body>
</html>

# 节点属性

nodeName 用于读取节点名称

  • nodeName 是只读的
  • 元素节点的 nodeName 与标签名相同
  • 属性节点的 nodeName 与属性名相同
  • 文本节点的 nodeName 始终是 #text
  • 文档节点的 nodeName 始终是 #document

注意: nodeName 始终包含 HTML 元素的大写字母标签名。

nodeValue 用于规定节点的值

  • 元素节点的 nodeValue 是 undefined 或 null
  • 文本节点的 nodeValue 是文本本身
  • 属性节点的 nodeValue 是属性值

nodeType 返回节点的类型(只读)

ownerDocument 返回当前节点的根元素(即 document 对象)

parentNode 返回当前节点的父节点(所有节点都仅有一个父节点)

childNodes 返回当前节点的所有子节点的节点列表( nodeList 类数组对象)

​ nodeList 对象实际上基于 DOM 结构动态执行查询的结果,DOM 结构的变化能够自动反映在 nodeList 对象中。可以通过方括号访问内部的值,但不能直接调用数组的方法。

firstChild 返回当前节点的首个子节点

lastChild 返回当前节点的最后一个子节点

nextSibling 返回当前节点之后相邻的同级节点

previousSibling 返回当前节点之前相邻的同级节点

# DOM 方法

getElementsByld() 返回带有指定 ID 的元素引用

node.getElementById("id");

getElementsByTagName() 返回带有指定标签名的所有元素

node.getElementsByTagName("tagname");

getElementsByClassName() 返回包含带有指定类名的所有元素的节点列表

document.getElementsByClassName("intro");

# 事件处理

# 事件委托

delegate 把目标节点的事件绑定到上层节点上

​ 原因:事件传播过程中,逐层冒泡总是能被上层节点捕获;优化代码,提升运行性能,真正将 HTML 与 JavaScript 分离;也能防止动态添加或删除节点时将注册的事件丢失。

# Ajax

​ Ajax (Asynchronous JavaScript and XML):利用 JS 脚本和 XML 数据实现客户端与服务器端之间快捷通信的一种技巧。

# 待补充

  1. filter () 方法
  2. 箭头函数
更新于

请我喝[茶]~( ̄▽ ̄)~*

页川木子 微信支付

微信支付

页川木子 支付宝

支付宝

页川木子 贝宝

贝宝