JS知识点梳理(3)-引用类型

Object 类型

  • 对象字面量表示法是对象定义的一种简写形式。

  • 有 2 种访问对象属性的方法:点表示法,方括号法。方括号法可以通过变量来访问属性。

  • Object.assign():将所有可枚举的自身属性的值从一个或多个 源对象复制到目标对象。其拷贝的是属性值,假如源对象的属性值是一个对象的引用,那么它也指向那个引用。可以使用 JSON 序列化,实现深拷贝。

    1
    2
    3
    4
    5
    6
    let obj = { a: 0, b: { c: 0 } };
    let deepClone = JSON.parse(JSON.stringify(obj));
    obj.a = 4;
    obj.b.c = 4;
    console.log(JSON.stringify(obj)); // {"a":4,"b":{"c":4}}
    console.log(JSON.stringify(deepClone)); // {"a":0,"b":{"c":0}}
  • Object.create(proto[, propertiesObject]): 使用指定的原型对象和属性 创建新对象。指定新对象的__proto__

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    // 1. 实现类式继承
    Rectangle.prototype = Object.create(Shape.prototype);
    Rectangle.prototype.constructor = Rectangle;
    // 2. 创建一个原型为null的空对象
    var o = Object.create(null);

    var o1 = {};
    // 3. 以字面量方式创建空对象就相当于
    o1 = Object.create(Object.prototype);

    // 4. 创建新对象,带着直到原型对象和属性
    o1 = Object.create(Object.prototype,{
    foo:{
    writable: true,
    cofigurable: true,
    value: "jiang"
    },
    // bar 成为所创建对象访问器属性,不可配置
    bar: {
    configurable: false,
    get: function() {
    return 10
    },
    set: function(value) {
    console.log("Stting o.bar to",value);
    }
    }
    })

    // 5. 创建一个以另一个空对象为原型,其拥有属性p的对象,
    // 省略的属性特性默认为false,即属性p 是 不可写,不可枚举,不可配置的
    var o2 = Object.create({}, { p: { value: 42 } });
    console.log(Object.getOwnPropertyDescriptor(o2, "p")); // Object {value: 42, writable: false, enumerable: false, configurable: false}
    var o3 = Object.create(
    {},
    {
    p: {
    value: 42,
    writable: true,
    enumerable: true,
    configurable: true
    }
    }
    );

    // 对象字面量创建的对象,其属性 的属性特性默认为false
    var o4 = { p: 23 };
    console.log(Object.getOwnPropertyDescriptor(o4, "p")); // Object {value: 23, writable: true, enumerable: true, configurable: true}
  • Object.defineProperty(obj,prop,descriptor):在一个对象上定义一个新属性,或者修改现有属性,并返回该对象.

    • writable 属性:设置为false时,该属性“不可写的”,即不能被重新赋值。
    • enumerable 属性: 定义了对象属性是否可以在for...in循环和Object.keys()中被枚举
    • configurable属性: 表示对象的属性是否可以被删除,以及除valuewritable特性外的其他特性是否可以被修改
  • Object.entries():返回一个给定对象自身可枚举属性的键值对数组([key, value]),同for..in循环遍历对象时返回的顺序一致,for..in循环还会枚举原型链中的属性,可通 hasOwnProperty()方法过滤

  • Object.freeze(obj):冻结一个对象,被冻结的对象不能被修改,即不能添加新属性,不能删除已有属性,不能修改对象已有属性的可枚举性,可配置性,可写性,也不能修改属性的值。该对象的原型也不能被修改。

  • Object.seal(): 封闭一个对象。阻止添加新属性并将所有现有属性标记为不可配置。

  • Object.preventExtensions():让一个对象变的不可扩展,也就是不能再添加新的属性。

  • Object.getPrototypeOf(obj):返回指定对象的原型(内部[[Prototype]]属性的值,即 __proto__属性的值)

  • Object.setPrototypeOf(obj,prototype):设置一个指定对象的原型(即,内部[[Prototype]]属性)到另一个对象或 null。因为更改对象的[[Prototype]]属性在浏览和 JS 引擎都是一个很慢的操作,应该避免设置一个对象的[[Prototype]],相反,应该使用Object.create()来创建带有想要的[[Prototype]]的新对象

Array 类型

创建数组实例

  • Array 构造函数
  • 数字字面量表示法
  • Array.from(arrayLike[, mapFn[, thisArg]]):从一个类似数组(拥有 length 属性和索引属性的对象)或可迭代对象(Map,Set)创建一个新的,浅拷贝的数组实例,可指定第二个参数,新数组中每个元素都会执行的回调函数。第三个参数,执行回调函数时this对象。

检测数组

  • 对于一个网页或一个全局作用域而言,至少有以下几种方式去判断一个值是否是数组
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var a = [];
    // 1. 基于 instanceof
    console.log(a instanceof Array);
    // 2. 基于constructor
    console.log(a.constructor === Array);
    // 3. 基于 isPrototypeOf
    console.log(Array.prototype.isPrototypeOf(a));
    // 4. getPrototypeOf
    console.log(Object.getPrototypeOf(a) === Array.prototype);
    // 5.基于Object.prototype.toString
    console.log(Object.prototype.toString.call(a) === "[object Array]");
    但以上方法都不准确,我们可以手动的指定某个对象的[[Prototype]]/__proto__属性为Array.prototype,从而导致该对象继承 Array 对象。
    1
    2
    var a = Object.create(Array.prototype);
    a.p = { c: 33 };
  • 如果网页中包含 对各框架(iframe),实际上就存在不同的全局作用域,从而存在不同版本的 Array 构造函数。ECMAScript 5 新增了Array.isArray(obj)方法

原型

js 中所有的数组方法均来自Array.prototype,和其他构造函数一样,可以通过扩展Arrayprototype属性上的方法来给所有数组实例增加方法。

Array.prototype本身就是一个数组,且长度为 0

方法

数组原型提供的方法主要分为三种:会改变自身值的,不会改变自身值的,遍历方法
由于Array.prototype的莫些属性被设置为[[DontEnum]],不能用一般的方法遍历,可以通过getOwnPropertyNames()来获取:

1
console.log(JSON.stringify(Object.getOwnPropertyNames(Array.prototype))); // ["length","constructor","concat","pop","push","shift","unshift","slice","splice","includes","indexOf","keys","entries","forEach","filter","map","every","some","reduce","reduceRight","toString","toLocaleString","join","reverse","sort","lastIndexOf","copyWithin","find","findIndex","fill"]

改变自身值的方法(9 个)

改变自身值的方法一共有 9 个,分别是pop,push,shift,unshift,splice,reverse,sort,以及 ES6 新增的copyWithin,fill
对于能改变自身值的方法,尽量避免再循环遍历中去改变原数组的项

pop,push
  • pop():删除一个数组的最后一个元素,并返回删除的元素

  • push(element1,...,elementN):添加一个或多个元素到数组末尾,并返回数组新的长度。

  • 同 pop 方法一样,push 方法也可应用到类数组对象上,如果 length 不能被转换成一个数值或者不存在,则插入的元素索引为 0,length 属性不存在时,江会创建它

    1
    2
    3
    4
    var o = {0:"football", 1:"basketball",length:1};
    var i = Array.prototype.push.call(o,"golfball");
    console.log(o); // Object {0: "football", 1: "golfball", length: 2}
    console.log(i); // 2
  • 实际上,push 方法是根据 length 属性来决定从哪开始插入给定的值。

    1
    2
    3
    4
    var o = {0:"football", 1:"basketball",length:1};
    var i = Array.prototype.push.call(o,"golfball");
    console.log(o); // Object {0: "football", 1: "golfball", length: 2}
    console.log(i); // 2
  • 结合pushapply方法,可实现数组的合并

    1
    2
    3
    4
    5
    var array = ["football", "basketball"];
    var array2 = ["volleyball", "golfball"];
    var i = Array.prototype.push.apply(array,array2);
    console.log(array); // ["football", "basketball", "volleyball", "golfball"]
    console.log(i); // 4
shift, unshift
  • shift():从数组中删除第一个元素,并返回该元素的值。此方法也能通过callapply方法作用于类数组对象上。
  • ubshift():将一个或多个元素添加到数组的开头,并返回该数组的新长度。
splice

splice(start[,deleteCount[,item1[,item2[, ...]]]])方法通过删除或替换现有元素或者原地添加新元素来修改数组,并返回被删除元素组成的一个数组。
start,指定修改的开始位置。超出数组的长度,则从数组末尾开始添加新元素。如果是负值,则位置等同于length+start.
deleteCount,指定要删除的元素个数。若等于 0,则不删除,但要至少添加一个新元素。
item1,item2,...要添加的新元素,从start位置开始。如果不指定,则splice()将只删除数组元素。
返回值, 由原数组中被删除元素组成的数组。如果没有删除,则返回一个空数组。

reverse

reverse()方法颠倒数组中元素的位置,并返回对数组的引用。

sort

sort([compareFn])方法对数组进行排序。compareFn参数是可选的,用来指定某种顺序进行排序的函数。如果省略,元素按照转换为的字符串的各个字符的 Unicode 位点进行排序。例如”Boy”将排在”apple”之前,数字 25 将排在 89 之前,因为转换为字符串”25”排在”89”之前。

1
2
3
4
5
6
7
8
var array = ["apple", "Boy", "Cat", "dog"];
var array2 = array.sort();
console.log(array); // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array); // true

array = [123, 1, 3, 25, 89];
var array3 = array.sort();
console.log(array3); // [1, 123, 25, 3, 89]

如果指定了comparefn排序函数,数组将按照调用该函数的返回值进行排序。

  • comparefn(a,b) < 0,a 将排在 b 前面;
  • comparefn(a,b) = 0,a 和 b 位置不变;
  • comparefn(a,b) > 0,a 将排在 b 的后面;
copyWithin

copyWithin(target[,start[,end]])方法复制数组的一部分到同一数组中的另一个位置,并返回它,不改变原数组的长度。
target,start,end必须为整数,如果为负,则等同于length+target/start/end.
如果start默认为 0;如果end默认为arr.length

1
2
3
4
5
console.log([1, 2, 3, 4, 5].copyWithin(-2)); // [1,2,3,1,2]
console.log([1, 2, 3, 4, 5].copyWithin(0, 3)); // [4,5,3,4,5]
console.log([1, 2, 3, 4, 5].copyWithin(0, 3, 4)); // [4,2,3,4,5]
console.log([1, 2, 3, 4, 5].copyWithin(-2, -3, -1)); // [1,2,3,3,4]
console.log([1, 2, 3, 4, 5].copyWithin(3, 2, 4)); // [1,2,3,3,4]
fill

fill(value[,start,[end]])方法用一个固定值填充一个数组从起始索引到终止索引的全部元素。
start,起始索引,默认值为 0;end,终止索引,默认值为arr.length

1
2
3
4
5
6
console.log([1, 2, 3].fill(4)); // [4,4,4]
console.log([1, 2, 3].fill(4, 1)); // [1,4,4]
console.log([1, 2, 3].fill(4, 1, 2)); // [1,4,3]
console.log([1, 2, 3].fill(4, 1, 1)); // [1,2,3]
console.log([1, 2, 3].fill(4, -3, -2)); // [4,2,3]
console.log(Array(3).fill(4)); //[4,4,4]

不改变自身的方法(8 个)

不改变自身的方法,分别为concat,join,slice,indexOf,lastIndexOf,includes,toString,toLocaleString

concat

concat()方法用于合并两个或多个数组,并返回一个新数组,不会更改现实有数组。

concat()方法不会改变this或任何作为参数提供的数组,而是返回一个浅拷贝

concat方法不传参,那么将基于原数组浅拷贝生成 一个新数组。

如果参数是对象引用concat将对象引用复制到新数组。原数组和新数组都引用相同的对象

join

join([separator])方法将一个数组或类数组对象的所有元素使用指定的分隔符连接成一个字符串并返回。
如果一个元素为nullundefined,它会被转换为空字符串。

1
2
const elements = ['Fire', 'Air', ,null,'Water'];
console.log(elements.join()); // "Fire,Air,,,Water"
slice

slice([begin[,end]]),将数组中一部分元素浅拷贝至新的数组对象,并返回这个新数组对象。

1
2
3
4
5
6
var array = [{ color: "yellow" }, 2, 3];
var array2 = array.slice(0, 1);
console.log(array2); // [{color:"yellow"}]
array[0]["color"] = "blue";
console.log(array2); // [{color:"bule"}]
console.log(array[0]); // {color: "blue"}
indexOf,lastIndexOf

indexOf(searchElement[,fromIndex]),lastIndexOf(searchElement[,fromIndex]),这两个方法都接受 2 个参数,要查找的元素,查找起点位置的索引。其中indexOf方法从数组的开头向后查找,lastIndexOf方法从数组的末尾向前查找。
这两个方法都返回被查找元素在数组中的位置索引,如果不存在则返回-1.

includes

inclues(valueToFind[,fromIndex])方法用来判断一个数组是否包含一个指定的值。返回一个布尔值。
如果传入了fromIndex,表示从fromIndex索引处开始查找。

toString,toLocaleString

toString方法返回数组的字符串形式,该字符串由数组中的每个元素的toString()返回值经调用join()方法连接组成。

toLocaleString方法,类似toString,有数组中的每个元素的toLocaleString()返回值经调用join方法连接组成。

  • Object: Object.prototype.toLocaleString()

  • Number: Number.prototype.toLocaleString()

  • Date: Date.prototype.toLocaleString()

    1
    2
    3
    var array = [{ name: "zz" }, 123, "abc", new Date()];
    var str = array.toLocaleString();
    console.log(str); // [object Object],123,abc,2020-3-31 07:34:50

遍历方法(12 个)

分别为forEach,map,filter,every,some,reduce,reduceRight,以及 ES6 新增的entries,find,findIndex,keys,values

forEach

forEach(callback(curretValue[,index [, array]])[,thisArg]),按升序为数组中含有效值的每一项执行一次callback函数。

  • 已经删除或者未初始化的元素将被跳过
  • 如果thisArg参数有值,则每次调用callback函数时,this都会指向thisArg参数。
  • forEach遍历的范围在第一次调用callback函数前就会确定。所以调用 forEach 后添加到数组中的项不会被 callback 访问到。
  • 如果数组莫一元素在迭代时被删除,这导致所有剩下的项上移一个位置。则之后的元素将被跳过。
map

map(callback(curretValue[,index [, array]])[,thisArg]),创建一个新数组,其结果时该数组中的每个元素都调用callback函数后返回的结果

  • map会生成一个新数组,如果你不打算使用返回的新数组却使用map是违背设计初衷的,应该是用forEachfor-of替代。
  • map不修改调用它的原数组本身,但可以在 callback 执行时改变原数组
  • map方法处理数组元素的 范围在callback方法第一次调用之前就已经确定了。所以调用map方法之后追加的数组元素不会被callback访问。
  • 如果存在的数组元素改变了,那么传给callback的值时map访问该元素时 的值。在map函数调用后但在访问元素之前,元素被删除的话,则无法访问到。
1
2
3
4
5
6
7
var xs = ["10", "10", "10"];
xs = xs.map(parseInt);
console.log(xs); // [10,NaN, 2]

// 1. parseInt("10", 0); 10
// 2. parseInt("10", 1); NaN
// 3. parseInt("10", 2); 2
filter

filter(callback(element[, index[, array]])[, thisArg]),使用传入的函数测试所以元素,并返回所有通过测试的元素组成的新数组。可理解为一个过滤器,过滤掉不符合条件的元素。

  • 被删除或者从未被赋值的元素不会被遍历到。
  • filter遍历的元素在第一次调用callback之前就已经确定了,所有在调用filter之后添加到数组中的元素不会被filter遍历到。
  • 如果已经存在的元素被改变了,则它们传入callback的值,是filter遍历到它们那一刻的值。
every

every方法测试一个数组内所有元素是否都能通过指定函数的测试,返回一个布尔值。

  • 被删除的元素或从来未被赋值的元素将不会被访问到
  • very 遍历的元素范围在第一次调用 callback 之前就已确定了。在调用 every 之后添加到数组中的元素不会被 callback 访问到
  • 如果数组中存在的元素被更改,则他们传入 callback 的值是 every 访问到他们那一刻的值
some

some方法测试数组中是否至少有 1 个元素通过指定函数的测试,返回一个布尔值。
只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false。

reduce, reduceRight

reduce(callback(accumulator, currentValue[, index[, array]]) [, initialValue]),对数组中的每个元素执行指定的reducer函数,最终返回函数累计处理的结果。是从左向右遍历。reduceRight则相反,是从右向左遍历。

  • accumulator: 累计器累计回调的返回值。是上一次调用回调时返回的累计值
  • currentValue:数组中正在处理的元素
  • index:数组中正在处理当前元素的索引。如果提供了initialValue,则起始索引为 0,否则从 1 起始。
  • initialValue: 作为第一次调用callback函数的第一个参数的值(即 accumoulator,累计器的初始值)。如果没有提供,则将使用数组的第一个元素

回调函数第一次执行时,accumulatorcurrentValue 的取值有两种情况:

  • 如果调用 reduce()时提供了 initialValueaccumulator 取值为 initialValuecurrentValue 取数组中的第一个值;
  • 如果没有提供 initialValue,那么 accumulator 取数组中的第一个值,currentValue 取数组中的第二个值。
find, findIndex

find(callback[, thisArg]),返回数组中满足提供的测试函数的第一个元素的值。否则返回undefined
findIndex(callback[, thisArg]),返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1

entries

entries()返回一个新的 数组迭代器对象(Array Iterator) 对象,该对象包含数组中每个索引的键/值对。

  • 返回的数组迭代器对象,它的原型上有next方法,可用于遍历迭代器取的原数组的[key,value].

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    var arr = ["a", "b", "c"];
    var iterator = arr.entries();
    console.log(iterator.next());
    /*{value: Array(2), done: false}
    done:false
    value:(2) [0, "a"]
    __proto__: Object
    */
    console.log(iterator.next());
    /*{value: Array(2), done: false}
    done:false
    value:(2) [1, "b"]
    __proto__: Object
    */
    console.log(iterator.next());
    /*{value: Array(2), done: false}
    done:false
    value:(2) [2, "c"]
    __proto__: Object
    */
  • 使用for..of循环,遍历迭代器对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var arr = ["a", "b", "c"];
    var iterator = arr.entries();
    for (let [k, v] of iterator) {
    console.log(`${k}: ${v}`);
    }
    /*
    0: a
    1: b
    2: c
    */
keys,values
  • keys(),返回一个包含数组中每个索引键 的数组迭代对象。
  • values(),返回一个包含数组每个索引的值的数组迭代对象。
  • 数组迭代器中存储的是原数组的地址,而不是数组元素值。如果数组中的元素改变,那么迭代器的值也会改变
    1
    2
    3
    4
    5
    6
    7
    8
    const arr1 = ["a", "b", "c"];
    const iterator = arr1.values();
    console.log(iterator); // Array Iterator { }
    console.log(iterator.next().value); // "a"
    arr1[1] = "n";
    arr1[2] = "jiang";
    console.log(iterator.next().value); // n
    console.log(iterator.next().value); // jiang
Symbol.iterator (@@iterator)

arr[Symbol.iterator](),返回数组的iterator方法,默认情况下,与values()返回值相同。即arr[Symbol.iterator]等同于values()函数。

1
2
3
4
5
var array = ["abc", "xyz"];
var iterator = array[Symbol.iterator]();
console.log(iterator.next().value); // abc
console.log(iterator.next().value); // xyz

也可以使用 for…of 循环进行 迭代

1
2
3
4
5
6
var array = ["abc", "xyz"];
var iterator = array[Symbol.iterator]();
for(let value of iterator) {
console.log(value);
}

RegExp 类型

语法

  • 字面量 /pattern/flags
  • 构造函数 new RegExp(pattern [,flags])
  • flags,标志可以具有以下值的任意组合:
    • g,全局匹配
    • i,忽略大小写
    • m,多行
    • u,将模式视为 Unicode 序列点的序列

以下表达式创建相同是正则表达:

1
2
3
/ab+c/i;
new RegExp("ab+c","i");
new RegExp(/ab+c/,"i");

RegExp 实例属性

RegExp 的每个实例都具有以下属性:

  • global: 布尔值,表示是否设置了 g 标志
  • ignoreCase: 布尔值, 是否设置了 i 标志
  • multiline: 布尔值,是否设置了 m 标志
  • lastIndex: 整数,表示开始搜素下一个匹配的字符位置,从 0 算起
  • source: 正则表达式的字符串表示

RegExp 实例方法

exec()

该方法是专门为捕获组而设计的。在一个指定字符串中执行一个搜素匹配,返回包含第一个匹配项信息的数组,在没有匹配的情况下返回 null

  • 如果匹配成功,exec()返回一个数组,第 0 项,表示匹配的全部字符串,其他项表示括号中的分组捕获。2 个额外属性,index,表示匹配项在字符串中的位置;input,表示应用正则表达式的字符串。同时更新正则表达式对象的lastIndex属性,表示下一次匹配开始的位置。
  • 如果匹配失败,exec()返回null,并将lastIndex重置为 0.

因为 RegExp 对象是有状态的,它们会更新lastIndex 属性,即使再次查找的字符串不是原来的字符串时,lastIndex也不会被重置,依旧从记录的lastIndex位置开始查找
exec()可用来对单个字符串中的多次匹配结果进行逐条的遍历,相比之下,String.prototype.match()只返回匹配到的结果。
如果只是为了判断是否匹配,可 使用RegExp.test(),返回布尔值String.search(),返回索引,或者 -1

test()

regexObj.test(str)方法执行一个检索,用来查看正则表达式与指定的字符串是否匹配,返回一个布尔值。
当 设置全局标志时,test()的执行会更新正则表达式lastIndex属性,连续执行test(),后续的执行将从lastIndex处开始匹配字符串。

1
2
3
var regex = /foo/g;
console.log(regex.test("foo")); // true
console.log(regex.test("foo123")); // false

正则表达式中特殊字符的含义

  • 字符类别(Character Classes)
    • .,匹配 任意单个字符。在字符集中,(.)就是匹配一个字面点.
    • \d,匹配任意阿拉伯数字,等价于[0-9]
    • \D,匹配任意一个不是阿拉伯数字的字符。等价于[^0-9]
    • \w,匹配任意字母、数字字符,还包括下划线。等价于[A-Za-z0-9_]
    • \W,匹配任意不是字母、数字、下划线字符的字符。等价于[^A-Za-z0-9_]
    • \s,匹配一个空白符,包括空格、制表符、换页符,换行符和其他 Unicode 空格。等价于[ \f\n\r\t\v​\u00a0\u1680​\u180e\u2000​\u2001\u2002​\u2003\u2004​ \u2005\u2006​\u2007\u2008​\u2009\u200a​\u2028\u2029​​\u202f\u205f​ \u3000]
    • \S,匹配一个非空白符。例如/\S\w*/匹配“foo bar”中的“foo”
    • \t, 匹配一个水平制表符(tab)
    • \r, 匹配一个回车符(carriage return)
    • \n,匹配一个换行符(linefeed)
    • \xhh,匹配编码为hh(2 个十六进制)的字符
    • \uhhhh,匹配 Unicode 值为hhhh(4 个十六进制)的字符
  • 字符集合 (Character Sets)
    • [xyz],一个字符结合,匹配集合中的任意一个字符。
    • [^xyz],一个反义字符组,它匹配任何不在括号内的字符。可使用连字符-[^abcd]等价于[^a-d]
  • 边界 (Boundaries)
    • ^,匹配输入开始,如果多行标记(multiline)设置为 true,该字符也会匹配一个断行符后的开始处。/^A/,匹配一个在开始处的 A
    • $,匹配输入结尾。/t$/匹配eat中的“t”, 但不匹配eater中的“t”
    • \b,匹配一个单词边界。
    • \B, 匹配一个分单词边界。
  • 分组 (Grouping)
    • (x),匹配x并且捕获匹配项。例如/(foo)/匹配且捕获”foo bar”中的”foo”.被匹配的子字符串可以在结果数组中的元素[1], ..., [n]中找到
    • \n,指向正则表达式中第 n 个括号中匹配的子字符串。例如/apple(,)\sorange\1/匹配”apple, orange, cherry, peach”中的”apple, orange,”
  • 数量词 (Quantifiers)
    • x*,匹配前面的模式x 0 次或多次
    • x+, 匹配前面的模式x 1 次或多次 等价于{1,}
    • x*?,x+?,同上面的*+一样匹配前面的模式x,但是最小可能匹配。例如/a+/匹配”caaaaaaaandy”所有的“a”;/a+?/匹配“caaaaaaaandy”中第一个”a”
    • x?,匹配前面的模式x, 0 次或 1 次
    • x|y,匹配xy
    • x{n},前面模式x连续出现 n 次时匹配
    • x{n,},前面模式x连续出现至少 n 次时匹配
    • x{n,m}, 前面模式x连续出现至少 n 次,至多 m 次时匹配
  • 断言 (Assertions), 以下断言只匹配x,y 不参与匹配
    • x(?=y),仅匹配被 y 跟随的 x。例如/Jack(?=Sprat)/,如果”Jack”后面跟着”Sprat”,则匹配
    • x(?!y),仅匹配不被 y 跟着的 x。例如/\d+(?!\.)/,只匹配不被.跟着的数字。/\d+(?!\.)/.exec("3.141"),匹配“141”
    • (?<=y)x,x 只有在 y 后面才匹配。/(?<=\$)\d+)/.exec("on the $100 bill, not @132"),匹配$符号后面的数字,“100”
    • (?<!y)x,x 只有不在 y 后面才匹配。/(?<!\$)\d+/.exec('it’s is worth about €90'),匹配不在$符号后面的数字,“90”

Function 类型

函数实际上对象,每个函数都是 Function 类型的实例。函数名是一个指向函数对象的指针。

函数声明和函数表达式

  • 解析器会率先读取函数声明,并使其在执行任何代码之前可用;即函数声明提升的过程,读取并将函数声明添加到执行环境
  • 函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行。

argumentsthis

  • arguments传递给函数的参数的类数组对象,且只能在函数内使用
  • 函数中this指向
    • 普通函数 this 指向 window
    • 定时器方法中的 this 指向 window
    • 构造函数中的 this 指向 实例对象
    • 对象方法中的 this 指向 实例对象
    • 原型对象上中 this 指向 实例对象
  • 箭头函数不会创建自己的 this,它只会从自己的作用域链的上一层继承 this

函数属性和方法

函数包含 2 个属性:lengthprototype

  • length,表示函数希望接受的命名参数的个数
  • prototype属性保存了所有实例方法,它是不可枚举的。

apply(),call(),bind()

  • apply()call(),在调用一个存在的函数时,你可以为其指定一个 this 对象。区别就是 call()方法接受的是参数列表,而 apply()方法接受的是一个参数数组。
  • bind(),创建一个新的绑定函数(BF bound function),其 this 值是bind()的第一个参数,其余参数作为新函数的参数,供调用时使用。

基本包装类型

为了便于操作基本类型值,ECMAScript 提供了 3 个特殊的引用类型:Boolean,Number,String.实际上,每当读取一个基本类型值时,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。 例如:

1
2
var s1 = "some text";
var s2 = s1.substring(2);

当第二行代码访问 s1 时,后台会自动完成以下处理:

    1. 创建 String 类型的一个实例
    1. 在实例上调用指定的方法
    1. 销毁这个实例

构造函数与转型函数

  • 使用new调用基本包装类型的构造函数,得到的是对应类型的实例,是对象 (typeof 返回 “object”)
  • 直接调用同名的转型函数,得到的是一个基本类型 (typeof返回对应 基本类型 “number” ,”boolean”,”string” )
1
2
3
4
5
6
7
8
var value = "25";
var number = Number(value); // 转型函数
console.log(number); // 25
console.log(typeof number); // "number"

var obj = new Number(value); // 构造函数
console.log(obj); // Number {[[PrimitiveValue]]: 25}
console.log(typeof obj); // "object"

Boolean 类型

Boolean 类型是与布尔值对应的引用类型。Boolean 类型的实例重写了valueOf(),返回基本类型值truefalse;重写了toString(),返回"true""false".

  • typeof操作符,对基本类型返回"boolean",对 Boolean 对象返回"object"
  • instanceof操作符,测试 Boolean 对象返回true,测试基本类型的布尔值则 返回false
1
2
3
4
5
6
ar falseObj = new Boolean(false);
var falseValue = false;
console.log(typeof falseObj); // "object"
console.log(typeof falseValue); // "boolean"
console.log(falseObj instanceof Boolean); // true
console.log(falseValue instanceof Boolean); // false

Number 类型

静态属性

  • Number.EPSILON: 两个可表示数之间的最小间隔(2.220446049250313e-16)
  • Number.MAX_SAFE_INTEGER: 最大的安全整数(2^53 - 1)
  • Number.MAX_VALUE: 最大正数(1.7976931348623157e+308)
  • Number.MIN_SAFE_INTEGER: 最小的安全整数 -Number.MAX_SAFE_INTEGER
  • Number.MIN_VALUE: 最小正数,即最接近 0 的正数。
  • Number.NaN: “非数字”值
  • Number.NEGATIVE_INFINITY: 负无穷(-Infinity)
  • Number.POSITIVE_INFINITY: 正无穷(Infinity)

静态方法

  • Number.isNaN(): 判断给定的值是否为 NaN
  • Number.isFinite(): 判断给定的值类型及本身是否是有穷数。和全局的isFinite()函数相比,该方法不会强制将一个非数值的参数转换成数值
    1
    2
    console.log(isFinite("123")); // true
    console.log(Number.isFinite("123")); // false
  • Number.isInteger(): 判断给定的值类型是”number”,且是整数
  • Number.isSafeInteger(): 判断给定的值是否为安全整数(-(2^53-1)~2^53-1)
  • Number.parseFloat(): 把一个字符串解析成浮点数,与全局的 parseFloat() 函数相同
  • Number.parseInt(string, radix): 依据指定基数radix(2-36 之间的整数),把字符串解析成整数。

将数值格式化字符串方法

  • toFixed(digits): 使用定点表示法来格式化一个数值。即四舍五入为指定小数位数。参数digits指定小数点后数值的个数,介于 0-20 之间,必要时用 0 来填充小数部分。
  • toExponential(fractionDigits): 以指数表示法返回该数值字符串表示形式。参数fractionDigits用来指定小数点后有几位数,字介于 0-20 之间(多余时,四舍五入处理),默认情况下用尽可能多的位数来显示数字。
  • toPrecision(precision): 以指定的精度返回该数值对象的字符串表示.参数precision用来指定有效数个数,介于 1-100 之间(多余时,四舍五入)

String 类型

字符方法

访问字符串中特定字符的方法
  • charAt(index):从一个字符串中返回指定的字符
  • charCodeAt(index): 返回 0-65535 之间的整数,表示给定索引出的 UTF-16 代码单元。
  • codePointAt(pos): 返回在字符串中的给定索引的 Unicode 编码点值
字符串操作方法
  • concat(string2,string3[,...,stribngN]): 将一个或多个字符串与原字符串连接合并,形成一个新字符串并返回。建议使用赋值操作符+,+= 代替 concat 方法
  • slice(beginIndex [, endIndex]):截取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。
  • substring(indexStart [, indexEnd]): 返回一个字符串在开始索引到结束索引之间的一个子集。
    • 如果indexStart等于indexEnd,返回一个空字符串
    • 如果省略indexEnd,则默认提取字符到字符串末尾
    • 如果任一参数小于 0 或者 为 NaN,则被当作 0
    • 如果indexStart大于indexEnd,则两参数调换。
字符串修剪方法
  • trim(): 从一个字符串的两端删除空白字符。
  • trimStart() / trimeLeft(): 从字符串开头删除空白字符
  • trimEnd() / trimRight(): 从字符串末尾删除空白字符
字符串位置方法
  • indexOf(searchValue[,fromIndex]):指定值第一次出现的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1。如果fromIndex的值小于 0,从 0 查找。
  • lastIndexOf():指定值最后一次出现的索引,从fromIndex 处从后向前搜索。如果没找到,则返回-1 。
字符串模式匹配方法
  • match(regexp): 返回字符串匹配正则表达式的结果 (Array)

    • 如果使用g标志,则返回匹配的所有结果,但不返回捕获组

    • 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)

      1
      2
      3
      4
      5
      var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
      var regexp = /[A-C]/g;
      var matches_array = str.match(regexp);

      console.log(matches_array); // ["A","B","C]
  • matchAll(regexp):返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。

    1
    2
    3
    4
    5
    6
    7
    8
      var regexp = /t(e)(st(\d?))/g;
    var str = "test1test2";
    var matches_array = str.match(regexp);
    console.log(matches_array); // ["test1", "test2"]
    var array = [...str.matchAll(regexp)];
    console.log(array);
    console.log(array[0]); //  ["test1", "e", "st1", "1", index: 0, input: "test1test2", groups: undefined]
    console.log(array[1]); // ["test2", "e", "st2", "2", index: 5, input: "test1test2", groups: undefined]
  • search(regexp): 返回字符中第一次匹配项的索引;否则,返回-1

字符串 判断方法
  • startsWith(searchString [, position]):判断当前字符串是否以另给定的子字符串开头,返回一个布尔值。
  • endsWith(searchString [, length]):判断当前字符串是否以另给定的子字符串结尾,返回一个布尔值。
    1
    2
    3
    4
    var str = "To be, or not to be, that is the question.";
    console.log(str.endsWith("question.")); // true
    console.log(str.endsWith("to be")); // false
    console.log(str.endsWith("to be", 19)); // true
  • includes(searchString [, position]): 判断一个字符串是否包含在另一个字符串中,返回一个布尔值
大小写转化方法
  • toUpperCase(): 字符串转换为大写形式
  • toLowerCase():字符串转换为小写形式
其他方法
  • fromCharCode(num1,...,numN):返回由指定的 UTF-16 代码单元序列创建的字符串
  • fromCodePoint(num1,...,numN): 返回由指定的代码点序列创建的字符串
  • padStart(targetLength [, padString]): 用指定字符串(默认为””)从当前字符串的开头开始填充,直到填充后长度达到指定长度,并返回填充后的字符串。
  • padEnd(targetLength [, padString]): 用指定字符串(默认为””)从当前字符串的末尾开始填充,直到填充后长度达到指定长度,并返回填充后的字符串。
1
2
3
4
5
6
7
8
9
10
11
console.log("abc".padStart(10)); // "       abc"
console.log("abc".padStart(10, "foo")); // "foofoofabc"
console.log("abc".padStart(6, "123465")); // "123abc"
console.log("abc".padStart(8, "0")); // "00000abc"
console.log("abc".padStart(1)); // "abc"

console.log("abc".padEnd(10));
("abc ");
console.log("abc".padEnd(8, "12345678")); // "abc12345"
console.log("abc".padEnd(10, "123")); // "abc1231231"
console.log("abc".padEnd(2)); // "abc"
  • split(separator [, limit]): 使用指定的分隔符字符串将一个字符串分割成子字符串数组。如果分隔符为空字符串,则将 str 原字符串中每个字符的数组形式返回。

    1
    2
    3
    4
    // 限制返回值中分隔元素的数量
    var myString = "Hello World. How are you doing?";
    var splits = myString.split(" ", 5);
    console.log(splits); // ["Hello", "World.", "How", "are", "you"]
  • replace(regexp|substr, newSubStr| function): 返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串.

    • regexp: 一个 RegExp 对象或其字面量,该正则所匹配 的内容被第二个参数的返回值替换掉
    • substr: 被newSubStr替换 的字符串。且仅被第一项替换掉
    • newSubStr: 用于替换第一个参数匹配到的结果
    • function: 用来创建新子字符串的函数,其返回值替换第一个参数匹配到的结果。 函数参数如下:
      • match,匹配的子串
      • p1,p2,..., 假设第一个参数是RegExp对象,则代表第 n 个括号匹配的字符串。
      • offset, 匹配到的子字符串在原字符串中的偏移量。
      • string, 被匹配的原字符串。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function swapper(match, p1, p2, offset, string) {
    console.log(arguments); // ["John Smith", "John", "Smith", 0, "John Smith"]
    return `${p2} <==> ${p1}`;
    }
    var regexp = /(\w+)\s(\w+)/;
    var str = "John Smith";
    console.log(str.replace(regexp, "$2 $1")); // Smith John

    var newStr = str.replace(regexp, swapper);
    console.log(newStr); // Smith <==> John

内置对象

内置对象是由 ECMAScript 实现提供的,不依赖于宿主环境的对象,这些对象在程序执行前就已经存在了。开发人员也不必显式的实例化内置对象,因为它们已经实例化了。常见的内置对象如Object,Array,String,Math等。

Global 对象

该对象是不存在的,但在某种意义上它作为一个”兜底对象”,实际上,所有的全局变量和函数都是 Global 对象的属性。

URL 编码方法

  • encodeURI()主要用于对整个 URI 进行编码,但它不会对本身属于 URI 的特殊字符(例如冒号,正斜杠,问号,井号)进行编码。 decodeURI()进行解码
  • encodeURIComponent()只要用于对 URI 中的某一段(查询字符串参数)进行编码,它会对所有的任何非标准字符进行编码。decodeURIComponent()进行解码。
1
2
3
4
var uri =
"https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURI";
console.log(encodeURI(uri)); // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
console.log(encodeURIComponent(uri)); // https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FJavaScript%2FReference%2FGlobal_Objects%2FencodeURI

Math 对象

Math 是一个内置对象,拥有一些数学常数属性和数学函数方法。Math 不是一个函数对象,它不是一个构造器。Math 所有的属性和方法都是静态的。

舍入方法

  • Math.ceil(): 向上舍入
  • Math.floor(): 向下舍入
  • Math.round(): 四舍五入

随机数

  • Math.random(): 返回大于 0 小于 1 的一个随机数;以下是一个随机产生 n-m 之间的整数值,包含 n,m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function randomRange(lowerValue, upperValue) {
    let choices = upperValue - lowerValue + 1;
    return Math.floor(Math.random() * choices + lowerValue);
    }
    var arr = [];
    for (let i = 0; i < 15; i++) {
    arr.push(randomRange(5, 10));
    }
    console.log(arr.join());