【JavaScript】
一、数据类型
1. JavaScript 中共有两种数据类型,分别是基本数据类型和引用数据类型(Object类型)。
基本数据类型:number、string、boolean、undefined、null、symbol(ES6新增)。
引用数据类型:对象、数组、函数。
symbol:ES6 入门教程
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。
ES6 引入了一种新的基本数据类型 Symbol,表示独一无二的值,Symbol 值通过 Symbol 函数生成。
let s = Symbol();
typeof s; // "symbol"
这就是说,对象的属性名现在有字符串和 Symbol 两种类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
注意,Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。
Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述。
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
如果 Symbol 的参数是一个对象,就会调用该对象的toString
方法,将其转为字符串,然后才生成一个 Symbol 值。
const obj = {
toString() {
return 'abc';
}
};
const sym = Symbol(obj);
sym // Symbol(abc)
注意,Symbol 函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的 Symbol 函数的返回值是不相等的。
Symbol 值不能与其他类型的值进行运算,会报错。但是,Symbol 值可以显式转为字符串。另外,Symbol 值也可以转为布尔值,但是不能转为数值。
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
let sym = Symbol();
Boolean(sym) // true
!sym // false
if (sym) {
// ...
}
Number(sym) // TypeError
sym + 2 // TypeError
2. JavaScript 中数据类型的两种判断方法:typeof 操作符和 instanceof 运算符。
typeof 操作符:返回一个字符串,表示未经计算的操作数的类型。
语法:typeof operand 或者 typeof(operand)
数据类型(返回值):
数值(number)、字符串(string)、布尔值(boolean)、未定义(undefined)、null(object)、symbol(symbol)、
对象(object)、数组(object)、函数(function)
// 数值 typeof 123 === 'number'; typeof Math.LN2 === 'number'; typeof Infinity === 'number'; typeof NaN === 'number'; // 尽管它是 "Not-A-Number" (非数值) 的缩写 typeof Number(1) === 'number'; // Number 会尝试把参数解析成数值 console.log(typeof Number); // function // 字符串 typeof '123' === 'string'; typeof (typeof 1) === 'string'; // typeof 总是返回一个字符串 typeof String(1) === 'string'; // String 将任意值转换为字符串,比 toString 更安全 console.log(typeof String); // function // 布尔值 typeof true === 'boolean'; typeof Boolean(1) === 'boolean'; // Boolean() 会基于参数是真值还是虚值进行转换 typeof !!(1) === 'boolean'; // 两次调用 ! (逻辑非) 操作符相当于 Boolean() console.log(typeof Boolean); // function // Undefined typeof undefined === 'undefined'; typeof declaredButUndefinedVariable === 'undefined'; typeof undeclaredVariable === 'undefined'; // ES6 新增的声明变量的方法:let、constant、class typeof newLetVariable; // ReferenceError typeof newConstVariable; // ReferenceError typeof newClass; // ReferenceError let newLetVariable; const newConstVariable = 'hello'; class newClass{}; // null 代表的是空指针 typeof null === 'object'; // Symbol typeof Symbol() === 'symbol'; typeof Symbol('foo') === 'symbol'; typeof Symbol.iterator === 'symbol'; console.log(typeof Symbol); // function // 数组 console.log(typeof []); // object console.log(typeof Array); // function // 对象 console.log(typeof {}); // object console.log(typeof Object); // function // 日期 typeof new Date() === 'object'; // 正则 typeof /regex/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1 typeof /regex/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1 // 除 Function 外的所有构造函数的类型都是 'object' typeof new Number(1) === 'object'; typeof new String('abc') === 'object'; typeof new Boolean(true) === 'object'; typeof new Array([]) === 'object'; typeof new Object({}) === 'object'; typeof new Function() === 'function'; // 函数 typeof function() {} === 'function'; typeof class C {} === 'function'; typeof Math.sin === 'function'; // 括号有无将决定表达式的类型。 var iData = 99; typeof iData + ' Wisen'; // 'number Wisen' typeof (iData + ' Wisen'); // 'string'
instanceof 运算符:返回一个布尔值,用于检测构造函数的
prototype
属性是否出现在某个实例对象的原型链上。
语法:object instanceof constructor, 即:
某个实例对象instanceof
某个构造函数。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/instanceof
console.log([] instanceof Array); //true console.log([] instanceof Object); //true console.log(Array instanceof Object); //true let a = function(){}; console.log(a instanceof Function); //true console.log(a instanceof Object); //true console.log(Function instanceof Object); //true let b = {}; console.log(b instanceof Object); //true console.log(Array instanceof Array); //false console.log(Function instanceof Function); //true console.log(Object instanceof Object); //true
function C(){}; var o = new C(); console.log(o instanceof C); // true,因为 Object.getPrototypeOf(o) === C.prototype C.prototype = {}; var o2 = new C(); console.log(o2 instanceof C); // true console.log(o instanceof C); // false,C.prototype 的指向改变了,指向了一个空对象,这个空对象不在 o 的原型链上.
var simpleStr = "This is a simple string"; var myString = new String(); var newStr = new String("String created with constructor"); var myDate = new Date(); var myObj = {}; var myNonObj = Object.create(null); simpleStr instanceof String; // 返回 false, 检查原型链会找到 undefined, simpleStr没有定义原型 myString instanceof String; // 返回 true newStr instanceof String; // 返回 true myString instanceof Object; // 返回 true myObj instanceof Object; // 返回 true, 尽管原型没有定义 ({}) instanceof Object; // 返回 true, 同上 myNonObj instanceof Object; // 返回 false, 一种创建非 Object 实例的对象的方法 myString instanceof Date; //返回 false myDate instanceof Date; // 返回 true myDate instanceof Object; // 返回 true myDate instanceof String; // 返回 false
安全检测数组的方法:Array.isArray(myObj) 或者 Object.prototype.toString.call(myObj) === "[object Array]"
要检测对象不是某个构造函数的实例时,你可以这样做:
if (!(mycar instanceof Car)) {
// Do something, like mycar = new Car(mycar)
}
二、数组方法
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from
1. JavaScript 中数组方法的返回值,及是否改变原数组的总结。
js数组(Array)库方法的返回值,是否改变原数组等方法的一些总结_array.reduce 返回的值是新值吗-CSDN博客
判断是否是数组:Array.isArray()
是否改变原数组:
可以改变也可以不改变原数组的方法:map、forEach、filter
能改变原数组的方法:push、pop、shift、unshift、splice、reverse、sort
不能改变原数组的方法:join、concat、slice、some、every、indexOf、lastIndexOf、reduce、reduceRight
返回值:
返回值为数组的方法:map、filter、splice、reverse、sort、concat、slice
splice:返回值是被删除的元素组成的数组。
返回值为其他的:
- forEach:无返回值。
- push:返回为添加新元素后的数组的长度。
- pop:返回被删除元素。
- shift:返回被删除元素。
- unshift:返回为添加新元素后的数组长度。
- join:返回为由制定字符分隔之后数组成员连接而成的字符串,默认以逗号(‘,’)隔开。
- some:true || false
- every:true || false
- indexOf:index || -1
- lastIndexOf:index || -1
2. JavaScript 中数组方法的区别,及应用场景的总结。
map 、forEach 和 filter 的相同点:
- 循环遍历数组中的每一项
- 两个参数(匿名函数-必选 和 this 的指向-可选),其中匿名函数有3个参数,分别是 item-必选(当前每一项)、index(索引值)、arr(原数组)
- 默认情况下,匿名函数中的 this 都是指向 window
- 只能遍历数组
map:map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
forEach:forEach()方法对数组的每个元素执行一次提供的函数。
filter:filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
map 和 forEach 的最大区别就在于:map 返回一个新数组,forEach 没有返回值, 即便你给 forEach 加上 return 也没用。其次在于:map不会对空数组进行检测,forEach 对于空数组是不会调用回调函数的。
splice:splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
参数:起始位置-必选(从0开始),要删除元素的个数-可选,增加的元素-可选。
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
sort:sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。
参数:比较规则的函数-可选。
slice:slice() 方法返回一个新的数组对象,这一对象是一个由
begin
和end
决定的原数组的浅拷贝(包括begin
,不包括end
)。原始数组不会被改变。
some() 方法测试数组中是不是有元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。只要有一个符合就返回 true。
every() 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。只要找到一个不符合的就返回 false。
indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
lastIndexOf() 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从
fromIndex
处开始。
reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
参数:两个参数(匿名函数-必选 和 初始值-可选),其中匿名函数有4个参数,分别是 acc-必选(累计值)、item-必选(当前每一项)、index-可选(索引值)、arr-可选(原数组)
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
reduceRight() 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。
参数:含义同上。
3. ES6 新增的数组方法。
新增的方法:扩展运算符、Array.from()、Array.of()、copyWithin()、fill()、find()、findIndex()、entries()、keys()、values()、includes()、 flat()、 flatMap()
是否改变原数组:
能改变原数组的方法:copyWithin()、fill()
不能改变原数组的方法:find()、findIndex()、entries()、keys()、values()、includes()、 flat()、 flatMap()
返回值:
返回值为新数组的方法:copyWithin()、fill()、 flat()、 flatMap()
返回值为其他的:
- find():value || undefined
- findIndex():index || -1
- entries():返回一个新的 Array Iterator 对象
- keys():返回一个包含数组中每个索引键的 Array Iterator 对象
- values():返回一个新的 Array Iterator 对象
- includes():true || false
扩展运算符(spread)是三个点(
...
)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。Array.from() 方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。
- 所谓类似数组的对象,本质特征只有一点,即必须有
length
属性。- 类似数组的对象有:DOM 操作返回的 NodeList 集合、函数内部的
arguments
对象- 可遍历的对象有:字符串、Set 和 Map
- Array.from() 还可以接受第二个参数,作用类似于数组的
map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。Array.from(arrayLike, x => x * x); // 等同于 Array.from(arrayLike).map(x => x * x); Array.from([1, 2, 3], (x) => x * x) // [1, 4, 9]
Array.of() 方法用于将一组值,转换为数组。这个方法的主要目的,是弥补数组构造函数
Array()
的不足。因为参数个数的不同,会导致Array()
的行为有差异。Array.of(3, 11, 8) // [3,11,8] Array.of(3) // [3] Array.of(3).length // 1 Array() // [] Array(3) // [, , ,] Array(3, 11, 8) // [3, 11, 8]
copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。
arr.copyWithin(target[, start[, end]])
fill() 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。
arr.fill(value[, start[, end]])
find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回 -1。
entries() 方法返回一个新的Array Iterator对象,该对象包含数组中每个索引的键/值对。
arr.entries()
keys() 方法返回一个包含数组中每个索引键的
Array Iterator
对象。values() 方法返回一个新的
Array Iterator
对象,该对象包含数组每个索引的值。includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
var newArray = arr.flat([depth]);
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 几乎相同,但
flatMap
通常在合并成一种方法的效率稍微高一些。var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) { // 返回新数组的元素 }[, thisArg])
var arr1 = [1, 2, 3, 4]; arr1.map(x => [x * 2]); // [[2], [4], [6], [8]] arr1.flatMap(x => [x * 2]); // [2, 4, 6, 8] // 只会将 flatMap 中的函数返回的数组 “压平” 一层 arr1.flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]
三、JS HTML DOM
1. DOM 操作
1. 获取节点
document.getElementById(id); // 返回对拥有指定id的第一个对象进行访问
document.getElementsByName(name); // 返回带有指定名称的节点集合,注意:Elements
document.getElementsByTagName(tagname); // 返回带有指定标签名的对象集合,注意:Elements
document.getElementsByClassName(classname); // 返回带有指定class名称的对象集合,注意:Elements2. 节点指针
parentObj.firstChild; // 获得一个节点的第一个子节点,此方法可以递归使用:parentObj.firstChild.firstChild.....
parentObj.lastChild; // 获得一个节点的最后一个节点,此方法可以递归使用:parentObj.lastChild.lastChild.....
parentObj.childNodes;// 获得节点的所有子节点,然后通过循环和索引找到目标节点neborNode.previousSibling;// 获取已知节点的相邻的上一个节点
neborNode.nextSibling; // 获取已知节点的相邻的下一个节点childNode.parentNode;// 得到已知节点的父节点
3. 创建节点
document.createElement(eName); // 创建一个节点
document.createAttribute(attrName); // 对某个节点创建属性
document.createTextNode(text); // 创建文本节点4. 插入节点
document.insertBefore(newNode,referenceChild); // 在某个节点前插入节点
parentNode.appendChild(newNode); // 给某个节点添加子节点5. 替换节点
replaceChild(newNode,oldNode); // 替换节点
6. 复制节点
cloneNode(true | false); // 复制某个节点,参数:是否复制原节点的所有属性
7. 删除节点
parentNode.removeChild(node);// 删除某个节点的子节点,node是要删除的节点
注意:IE会忽略节点间生成的空白文本节点(例如,换行符号),而Mozilla不会这样做。在删除指定节点的时候不会出错,但是如果要删除最后一个子结点或者是第一个子结点的时候,就会出现问题。这时候,就需要用一个函数来判断首个子结点的节点类型。
元素节点的节点类型是 1,因此如果首个子节点不是一个元素节点,它就会移至下一个节点,然后继续检查此节点是否为元素节点。整个过程会一直持续到首个元素子节点被找到为止。通过这个方法,我们就可以在 Internet Explorer 和 Mozilla 得到正确的方法。8. 属性操作
getAttribute(name); // 通过属性名称获取某个节点属性的值
setAttribute(name,value); // 修改某个节点属性的值
removeAttribute(name); // 删除某个属性9. 文本操作
appendData(data); // 将data加到文本节点后面
deleteData(start,length); // 将从start处删除length个字符
insertData(start,data); // 在start处插入字符,start的开始值是0;
replaceData(start,length,data); // 在start处用data替换length个字符
splitData(offset); // 在offset处分割文本节点
substringData(start,length); // 从start处提取length个字符10. 改变 HTML 输出流
在 JavaScript 中,document.write() 可用于直接向 HTML 输出流写内容。
11. 改变 HTML 内容
innerHTML属性:document.getElementById(id).innerHTML=new HTML。
12. 改变 HTML 属性
document.getElementById(id).attribute=new value。
13. 改变 HTML 样式
document.getElementById(id).style.property=new style。
2. DOM 事件
向 button 元素分配 onclick 事件:
- <button οnclick="displayDate()">点我</button>
- document.getElementById("myBtn").οnclick=function(){displayDate()};
各种事件:
- onload 和 onunload 事件会在用户进入或离开页面时被触发。onload 事件可用于检测访问者的浏览器类型和浏览器版本,并基于这些信息来加载网页的正确版本。onload 和 onunload 事件可用于处理 cookie。
- onchange 事件常结合对输入字段的验证来使用。
- onmouseover 和 onmouseout 事件可用于在用户的鼠标移至 HTML 元素上方或移出元素时触发函数。
- onmousedown, onmouseup 以及 onclick 构成了鼠标点击事件的所有部分。首先当点击鼠标按钮时,会触发 onmousedown 事件,当释放鼠标按钮时,会触发 onmouseup 事件,最后,当完成鼠标点击时,会触发 onclick 事件。
事件监听:
addEventListener() 方法:element.addEventListener(event, function, useCapture); 第一个参数是事件的类型 (如 "click" 或 "mousedown"),第二个参数是事件触发后调用的函数,第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。
- addEventListener() 方法用于向指定元素添加事件句柄。
- addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。
- 你可以向一个元素添加多个事件句柄。
- 你可以向同个元素添加多个同类型的事件句柄,如:两个 "click" 事件。
- 你可以向任何 DOM 对象添加事件监听,不仅仅是 HTML 元素。如: window 对象。当用户重置窗口大小时添加事件监听:
window.addEventListener("resize", function(){ document.getElementById("demo").innerHTML = sometext; });
- addEventListener() 方法可以更简单的控制事件(冒泡与捕获)。默认值为 false, 即冒泡传递(由内到外),当值为 true 时, 事件使用捕获传递(由外到内)。
removeEventListener() 方法:移除监听事件。
END