关于前端:JavaScript-StringArrayObjectDate-常用方法小结

6次阅读

共计 21263 个字符,预计需要花费 54 分钟才能阅读完成。

JavaScript String、Array、Object、Date 罕用办法小结

  反正闲着也是闲着,略微整顿总结了一下 JavaScript 字符串、数组、对象、工夫的罕用办法,阿彪出品,必属精品 / 滑稽。

字符串(String)

charAt

// 返回在指定地位的字符
"12345".charAt(0); // 1

charCodeAt

// 返回在指定的地位的字符的 Unicode 编码
"12345".charCodeAt(0); // 49

concat

// 连贯字符串
"123".concat("456"); // "123456"

indexOf/lastIndexOf

// 查看字符呈现的地位
"123451".indexOf("1"); // 0
"123451".indexOf("1"); // 5

match

// match() 办法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。该办法相似 indexOf() 和 lastIndexOf(),然而它返回指定的值,而不是字符串的地位。"doubleam 666 123".match(/\d+/g); // ["666", "123"]

search

// search() 办法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,如果没有找到任何匹配的子串,则返回 -1。"doubleam 666 123".search("6"); // 9
"doubleam 666 123".search("9"); // -1

replace

// replace() 办法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。"doubleam 666".replace("666", "999"); // "doubleam 999"
"doubleam 666".replace(/(doubleam)\s(666)/g, "$2 $1"); // 666 doubleam
"doubleam 666".replace(/(doubleam)\s(666)/g, function($1, $2, $3){console.log($1, $2, $3);//doubleam 666, doubleam, 666
  return $1 + $2 + $3;
}); // doubleam 666doubleam666

slice

// 提取字符串的片断,并在新的字符串中返回被提取的局部。// str.slice(start, end);
// start: 要抽取的片断的起始下标。如果是正数,则该参数规定的是从字符串的尾部开始算起的地位。也就是说,-1 指字符串的最初一个字符,-2 指倒数第二个字符,以此类推。// end:紧接着要抽取的片段的结尾的下标。若未指定此参数,则要提取的子串包含 start 到原字符串结尾的字符串。如果该参数是正数,那么它规定的是从字符串的尾部开始算起的地位。"i love oqm".slice(0, 1); // 'i'
"i love oqm".slice(2); // 'love oqm'
"i love oqm".slice(-3); // 'oqm'

substr

// 同上
"i love oqm".substr(0, 1); // 'i'
"i love oqm".substr(2); // 'love oqm'
"i love oqm".substr(-3); // 'oqm'

substring

// 同上,但不反对正数,尾部开区间 [start, end)。"i love oqm".substring(0, 1); // 'i'
"i love oqm".substring(2); // 'love oqm'
"i love oqm".substring(0, 4); // 'i lo'

split

// 把字符串宰割为字符串数组
"1,2,3,4,5".split(); // ["1,2,3,4,5"]
"1,2,3,4,5".split(""); // ["1",",","2",",","3",",","4",",","5"]"1,2,3,4,5".split(","); // ["1","2","3","4","5"]

toLocaleLowerCase/toLocaleUpperCase

// 把字符串转换为小 / 大写
'aBc'.toLocaleLowerCase(); // 'abc'
'aBc'.toLocaleUpperCase(); // 'ABC'

toLowerCase/toUpperCase

// 把字符串转换为小 / 大写
'aBc'.toLowerCase(); // 'abc'
'aBc'.toUpperCase(); // 'ABC'

for-of

for-of 能够遍历字符串,除了遍历字符串,这个遍历器最大的长处是能够辨认大于 0xFFFF 的码点,传统的 for 循环无奈辨认这样的码点。

at

// at 办法能够辨认 Unicode 编号大于 0xFFFF 的字符,返回正确的字符。'我爱你'.at(0); // "我"

includes

// 查看指定字符是否存在与字符串中
'doubleam'.includes('d'); // true

startsWith/endsWith

// 查看指定字符是否存在与字符串结尾 / 结尾
'doubleam'.startsWith('a'); // false
'doubleam'.endsWith('m'); // true

repeat

// repeat 办法返回一个新字符串,示意将原字符串反复 n 次。'doubleam'.repeat(3); // "doubleamdoubleamdoubleam"
'doubleam'.repeat(0); // ""

padStart/padEnd

// 字符串长度补全,默认应用空格补全长度。"1.01".padEnd(5, "0"); // "1.010"
// 如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。"1.010".padEnd(5, "0"); // "1.010"
// 如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。'09-28'.padStart(10, 'yyyy-mm-dd'); // "yyyy-09-28"

trim

// 去除首尾空格
"doubleam".trim(); // "doubleam"

trimLeft/trimRight/trimStart/trimEnd

字面意思

生成 DOM string

// 乏味
"baidu".link('baidu.com'); // "<a href=\"baidu.com\">baidu</a>"
"baidu".sub(); // "<sub>baidu</sub>"

数组(Array)

reduce

// 应用 console.time('test'); 与 console.timeEnd('test'); 测试发现,数组遍历速度 for > for-of > forEach > filter > map > for-in(可实用于对象)/reduce > $.each([1, 2, 3, 4], (index, value) => console.log(value));(JQ)
// 以下介绍遍历办法均不可跳出,且 map 为迭代严格意义上不算循环,若想实现跳出或局部判断可应用 ES6 for-of、find 或 some...

// reduce 办法有两个个参数,第一个参数是一个 callback,用于针对数组项的操作(total, currentValue, currentIndex, selfArray);第二个参数则是传入的初始值,这个初始值用于单个数组项的操作。须要留神的是,reduce 办法返回值并不是数组,而是返回通过叠加解决后的后果;不扭转原数组。[1, 2, 3, 4].reduce((x, y) => x + y); //10
let testArr = [{'name':'a', 'age':1}, {'name':'b', 'age':2}, {'name':'c', 'age':3}, {'name':'d', 'age':4}];
testArr.reduce(function (total, currentValue, currentIndex, selfArray) {
  // total 为上一次调用返回的值,或者是提供的初始值 0。// 0,1,3,6,10
  console.log(selfArray[currentIndex].name); // a,b,c,d
  return total + currentValue.age;
}, 0); // 10

map

// map 办法对数组的每一项都运行给定的函数,返回每次函数调用的后果组成一个新数组,不扭转原数组。[1, 2, 3, 4].map((value, index, selfArray) => value * 10); // [10,20,30,40]

forEach

// forEach 数组遍历
[1, 2, 3, 4].forEach(function(value, index, selfArray) {//do something});

push

// push 办法可向数组的开端增加一个或多个元素,并返回新的长度,扭转原数组。let testArr = [1, 2, 3, 4];
testArr.push(5, 6); // 6
console.log(testArr); // [1,2,3,4,5,6]

pop

// pop 办法用于删除并返回数组的最初一个元素,扭转原数组。let testArr = [1, 2, 3, 4];
testArr.pop(); // 4
console.log(testArr); // [1,2,3]

shift

// shift 办法用于把数组的第一个元素从其中删除,并返回第一个元素的值,扭转原数组。let testArr = [1, 2, 3, 4];
testArr.shift(); // 1
console.log(testArr); // [2,3,4]

unshift

// unshift 办法可向数组的结尾增加一个或更多元素,并返回新的长度,扭转原数组。let testArr = [1, 2, 3, 4];
testArr.unshift(-1, 0); // 6
console.log(testArr); // [-1,0,1,2,3,4]

concat

// concat 办法用于连贯两个或多个数组,返回新数组。[1].concat([2],[3],[4]); // [1,2,3,4]

join

// join 办法用于把数组中的所有元素放入一个字符串,元素是通过指定的分隔符进行分隔的,默认应用 ',' 号分隔,不扭转原数组,返回字符串。[1, 2, 3, 4].join('/'); // 1/2/3/4

filter

// filter 对数组的每一项都运行给定的函数,返回后果为 true 组成的数组,不扭转原数组,返回新数组。[null, undefined, 1, '', 0,'biugle'].filter(Boolean); // [1,'biugle']
[null, undefined, 1, '', 0,'biugle'].filter((value, index, selfArray) => value =='biugle'); // [biugle]

every

// every 对数组的每一项都运行给定的函数,每一项都返回 true,则返回 true,不扭转原数组,返回 bool。[1, 2, 3, 4].every((value, index, selfArray) => value < 5); // true

some

// some 对数组的每一项都运行给定的函数,任意一项返回 true,则返回 true,不扭转原数组,返回 bool。[1, 2, 3, 4].some((value, index, selfArray) => value == 1); // true

at

// at 获取指定下标元素,同 array[index]。[1, 2, 3, 4].at(3); // 4

slice

// slice 返回一个新的数组,蕴含从 start 到 end (尾部开区间,不包含该元素。)的 selfArray 中的元素,不扭转原数组。let testArr = [1, 2, 3, 4];
testArr.slice(0, 3); // [1,2,3]
console.log(testArr); // [1,2,3,4]

splice

// splice 办法可删除从 index 处开始的零个或多个元素,并且用参数列表中申明的一个或多个值来替换那些被删除的元素。// 如果从 selfArray 中删除了元素,则返回的是含有被删除的元素的数组。该办法会间接对数组进行批改。let testArr = [1, 2, 3, 4];
testArr.splice(1, 2, 5, 6); // [2, 3] ps: 在 index 为 1 开始,删除 2 个元素,增加 5, 6。console.log(testArr); // [1, 5, 6, 4]

sort

// sort 排序依照 Unicode Code 地位排序,默认升序,扭转原数组。// 需传入比拟函数 function(a, b),a/ b 为相比拟的值。// 若返回一个 < 0 的值,则 a 应该在 b 后面。// 若返回 = 0 的值,a 与 b 点地位绝对不变。// 若返回一个 > 0 的值,则 a 应该在 b 前面。[1, 2, 4, 3, 6, 5].sort(); // [1, 2, 3, 4, 5, 6]
[1, 2, 4, 3, 16, 15].sort(); // [1, 15, 16, 2, 3, 4]
[1, 2, 4, 3, 16, 15].sort((a, b) => a - b); // [1, 2, 3, 4, 15, 16]
[1, 2, 4, 3, 16, 15].sort(function(a, b) {console.log(`${b} - ${a} = ${b - a}`); 
  return b - a;
}); // [16, 15, 4, 3, 2, 1]
['aaa', 'bb', 'c'].sort(); // ["aaa", "bb", "c"]
['aaa', 'bb', 'c'].sort().sort((a, b) => a.length - b.length); // ["c", "bb", "aaa"]

reverse

// reverse 办法用于颠倒数组中元素的程序,返回的是颠倒后的数组,扭转原数组。let testArr = [1, 2, 3, 4];
testArr.reverse();
console.log(testArr); // [4, 3, 2, 1]

// 咱们也能够通过 sort 来进行数组颠倒,只需返回 < 0 的值即可。[1, 2, 3, 4, 5].sort(() => -1); // [5, 4, 3, 2, 1]

indexOf

// indexOf 和 lastIndexOf 都承受两个参数:查找的值、查找起始地位。不存在,返回 -1,存在,返回地位。indexOf 是从返回后查找,lastIndexOf 是从后往前查找。let testArr = [1, 2, 3, 1];
testArr.indexOf(1); // 0
testArr.lastIndexOf(1); // 3
testArr.indexOf(4); // -1

find

// find 和 findIndex 传入一个回调函数,找到数组中合乎以后搜寻规定的第一个元素,返回它,并且终止搜寻。findIndex 返回的是下标。let testArr = [1, 2, 3, 4];
testArr.find((item, index, selfArray) => item > 1); // 2
testArr.findIndex((item) => item > 1); // 1

fill

// fill(value, start, end) 用新元素替换掉数组内的元素,能够指定替换下标范畴(尾部开区间),扭转原数组。let testArr = [1, 2, 3, 4];
testArr.fill(0, 1, 3); // [1, 0, 0, 4]
testArr.fill(0, 1, 100); // [1, 0, 0, 0]

copyWithin

// copyWithin(target, start, end) 抉择数组的某个下标,从该地位开始复制数组元素,默认从 0 开始复制,也能够指定要复制的元素范畴(尾部开区间),扭转原数组。let testArr = [1, 2, 3, 4];
testArr.copyWithin(2, 0, 2); // [1, 2, 1, 2] ps: 从 index 2 开始复制 [0,2) 之间的元素,所以原数组 3,4 被替换为 1,2。

from

// from 将相似数组的对象(array-like object)和可遍历(iterable)的对象转为真正的数组。Array.from([1, 2, 3, 4]); // [1,2,3,4]
Array.from('1234'); // ['1','2','3','4']

// 数组克隆咱们也能够应用此办法,或者应用 concat,亦或是应用 ... 开展运算符。

of

// of 用于将一组值,转换为数组,这个办法的次要目标,是补救数组构造函数 Array() 的有余。// 因为参数个数的不同,会导致 Array() 的行为有差别。Array(1, 2, 3); // [1,2,3]
Array(4); // [empty*4]
Array.of(1, 2, 3); // [1,2,3]
Array.of(4); // [4]

entries

// entries 返回迭代器,返回键值对。// 数组
let testArr = ['a', 'b', 'c'];
for(let value of testArr.entries()) {console.log(value); // [0, 'a'],[1, 'b'],[2, 'c']
}
// Set,(add,delete,size,forEach,has,keys,values,clear)Set 构造不会增加反复的值,也可用于数组去重。[...new Set([1, 1, 2, 2, 3, 4, 5])]; 或 Array.from(new Set([1, 1, 2, 2, 3, 4, 5])); // [1, 2, 3, 4, 5]
// 去重还能够利用对象 key,或者 Array 的 filter 办法加上 indexOf 来实现。new Set([NaN, NaN, {}, {}]); // [NaN, {}, {}]
let testSet = new Set(testArr);
for(let value of testSet.entries()) {console.log(value); // ['a', 'a'],['b', 'b'],['c', 'c']
}
// Map,(set,get,delete,size,forEach,has,keys,values,clear)个别用于疾速查问,性能高。let testMap = new Map([['a', 'a'], ['b', 'b']]);
testMap.set('c', 'c');
for(let value of testMap.entries()) {console.log(value); // ['a', 'a'],['b', 'b'],['c', 'c']
}

values

// values 返回迭代器,返回键值对的 value。// 数组
let testArr = ['a', 'b', 'c'];
for(let value of testArr.values()) {console.log(value); //'a' 'b' 'c'
}
// Set
let testSet = new Set(['a', 'b', 'c']);
for(let value of testSet.values()) {console.log(value); // 'a' 'b' 'c'
}
// Map
let testMap = new Map([['a', 'a'], ['b', 'b'], ['c', 'c']]);
for(let value of testMap.values()) {console.log(value); // 'a' 'b' 'c'
}

keys

// keys() 返回迭代器,返回键值对的 key。// 数组
let testArr = ['a', 'b', 'c'];
for(let value of testArr.keys()) {console.log(value); //'0' '1' '2'
}
// Set
let testSet = new Set(['a', 'b', 'c']);
for(let value of testSet.keys()) {console.log(value); // 'a' 'b' 'c'
}
// Map
let testMap = new Map([['a', 'a'], ['b', 'b'], ['c', 'c']]);
for(let value of testMap.keys()) {console.log(value); // 'a' 'b' 'c'
}

includes

// includes 判断数组中是否存在该元素,参数:查找的值、起始地位,能够替换 ES5 时代的 indexOf 判断形式。// indexOf 判断元素是否为 NaN,会判断谬误。let testArr = [1, 2, 3, 4, NaN];
testArr.includes(1, 2); // false ps: 从 index 2 开始查。testArr.includes(NaN); // true
testArr.indexOf(NaN); // -1

flat

// flat 数组降维打击,返回新数组,不扭转原数组。[1, 2, [3, 4], [5, [6, 7]], 8].flat(); // [1, 2, 3, 4, 5, [6, 7], 8]
[1, 2, [3, 4], [5, [6, 7, [8]]], 9].flat(2); // [1, 2, 3, 4, 5, 6, 7, [8], 9]
[1, 2, [3, 4], [5, [6, 7, [8]]], 9].flat(3); // [1, 2, 3, 4, 5, 6, 7, 8, 9]

对象(Object)

create

// Object.create() 办法创立一个新对象,应用现有的对象来提供新创建的对象的__proto__(外面的属性属于新对象本人),其实简略来说就是扭转创建对象的原型指向。let testObj = {name: 'doubleam', age: 21};
let extendObj = Object.create(testObj, {
  gender: {
    value: 'man', // 属性值
    writable: true, // 是否能够重写值
    enumerable: true, // 是否可枚举
    configurable: true // 是否能够批改以上几项配置
  }
});
extendObj; // {gender: 'man'}
extendObj.__proto__; // {name: "doubleam", age: 21}
extendObj.name; // doubelam
// enumerable 是否可枚举
// for-in 遍历对象所有属性(包含原型上的属性)。// Object.keys 只能遍历本身属性
// JSON.stringify 只能序列化本身属性
for(item in extendObj){console.log(item); // gender,name,age
  // 若 enumerable = false,那么此处打印为 name,age。}
Object.keys(extendObj); // gender ps: 多个属性按 ascii 顺序排列,vue 中应用 v-for 遍历也受此影响。// 若 enumerable = false,那么此处值为空 []。// Object.create 与 new Object() 是有区别的,比方 Object.create(null) 创立的对象是一个空对象,在该对象上没有继承 Object.prototype 原型链上的属性或者办法 (toString(),hasOwnProperty()等)。// 利用 create 实现 new
function Dog(name) {this.name = name;}
Dog.prototype.speak = function () {console.log('汪汪汪');
};
function _new(fn, ...arg) {// let obj = {}
  // obj.__proto__ = fn.prototype
  let obj = Object.create(fn.prototype); // 先扭转原型指向
  fn.call(obj, ...arg); // 再调用构造函数
  return obj;
}
let blackDog = _new(Dog, '小黑');

console.log(blackDog);
console.log(blackDog.name);
blackDog.speak();

// 继承则能够通过 prototype 构造函数 es6-extend 等形式实现 https://www.cnblogs.com/humin/p/4556820.html

assign

// Object.assign(target, source1, source2) 办法用于对象的合并,将源对象(source)的所有可枚举属性,复制到指标对象(target),若 target 与 source 存在雷同属性,则会被后呈现的笼罩。拷贝的属性是有限度的,只拷贝源对象的本身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。let target = {a: 0, b: 1};
let source1 = {b: 2, c: 3};
let source2 = {c: 4};
Object.assign(target, source1, source2); // {a:0, b:2, c:4}

// 深浅拷贝
// Object.assign()拷贝的是属性值。如果源对象的属性值是一个对象的援用,那么它也只指向那个援用。// 如果对象的属性值为简略类型(如 number,string,boolean),通过 Object.assign({}, source); 失去的新对象为深拷贝。// 但如果属性值为对象(object)或其它援用类型时,那对于这个对象而言其实是浅拷贝的。// 总结:当被复制合并的对象中只有一级属性,没有二级属性的时候,此办法为深拷贝,然而对象中有对象的时候,此办法,在二级属性当前就是浅拷贝。// 如果要实现深拷贝,能够应用 JSON.parse(JSON.stringify(source)); 或者应用 JQ $.extend()。// 也能够通过 ... 开展运算符克隆对象:newObj = {...obj1, ...obj2}; 数组转对象也能够应用 ... 开展运算符:newObj = {...arr};
let testObj = {a: 1, obj: {a: 2}};
let copyObj = Object.assign({}, testObj);
copyObj.obj.a = 3;
console.log(testObj.obj.a) //3

// 特例 空类型 undefined,null
Object.assign(target, undefined) === target; // true
Object.assign(target, null) === target; // true
Object.assign([1, 2, 3, 4], [5, 6, 7]); // [5, 6, 7, 4]

// js 原始数据类型: number,string,boolean,undefined,null,object【ES6 又新增 Symbol 还有谷歌的 bigint】。// 根本数据类型(简略类型),值类型: number,string,boolean。// 简单数据类型(援用类型),object。// 空类型 undefined,null。// 值类型的值在栈中存储,值类型传递,传递的是值。// 援用类型的值,对象在堆上存储,地址在栈上存储。援用类型传递,传递的是地址(援用)。let num = 10; // 值类型,值在栈上。var obj = {}; // 简单类型,对象在堆,地址 (援用) 在栈。且应用 var 关键字不仅能够变量晋升,在页面敞开之前始终在内存中。// 提一下类型判断,typeof 个别只能返回如下几个后果:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。// 如果咱们要判断数组、工夫等其余 new 对象,咱们能够通过原生的办法,或者构造函数 constructor 来判断。// Array.isArray(arr); 或 typeof arr === 'object' && arr.constructor === Array; 或 Array.prototype.isPrototypeOf(arr);
// typeof date === 'object' && date.constructor === Date;

// 当然也能够应用 instanceof 该运算符用于检测构造函数的 prototype 属性是否呈现在某个实例对象的原型链上。// ({}) instanceof Object; // true
// ([]) instanceof Object; // true 数组是对象的子类
// ([]) instanceof Array; // true
// (new Date()) instanceof Object; // true
// (new Date()) instanceof Date; // true 同上

//【toString】还能够应用 Object.prototype.toString.call(val); 来判断类型
// Object.prototype.toString.call(1); // '[object Number]'
// Object.prototype.toString.call({}); // '[object Object]'
// Object.prototype.toString.call([]); // '[object Array]'
// Object.prototype.toString.call(function(){}); // '[object Function]'
// Object.prototype.toString.call(new Date); // '[object Date]'

// Since JavaScript 1.8.5
// Object.prototype.toString.call(null); // '[object Null]'
// Object.prototype.toString.call(); // '[object Undefined]'

toString

  • toString 办法返回一个示意该对象的字符串。
对象 返回值
Array 以逗号宰割的字符串,如 [1, 2] 的 toString 返回值为 1,2
Boolean true
Date 可读的工夫字符串,如 Tue Aug 25 2020 19:30:17 GMT+0800 (中国规范工夫)
Function 申明函数的 JS 源代码字符串
Number 数字值
Object [object Object]
String 字符串值
let num = 3;
let str = '3';
let bool = true;
let obj = {test: '123', example: 123};
let func = function () {console.log('example');
};
var arr = ['test', 'example'];

num.toString(); // "3"
str.toString(); // "3"
bool.toString(); // "true"
obj.toString(); // "[object Object]"
func.toString(); // "function () {console.log('example'); }"
arr.toString(); // "test,example"

// 每个对象都有一个 toString() 办法,当该对象被示意为一个文本值时,或者一个对象以预期的字符串形式援用时主动调用。默认状况下,toString() 办法被每个 Object 对象继承。如果此办法在自定义对象中未被笼罩,toString() 返回 "[object type]",其中 type 是对象的类型。// 下面【toString】咱们也提到能够用他来判断类型
// 还能够自定义一个办法,来取代默认的 toString() 办法。该 toString() 办法不能传入参数,并且必须返回一个字符串。自定义的 toString() 办法能够是任何咱们须要的值,但如果它附带无关对象的信息,它将变得十分有用。function Dog(name, breed, color, sex) {
  this.name = name;
  this.breed = breed;
  this.color = color;
  this.sex = sex;
}
Dog.prototype.toString = function dogToString() {return `Dog ${this.name} is a ${this.sex} ${this.color} ${this.breed}`;
};

var theDog = new Dog('Hellen', 'Lab', 'red', 'female');
theDog.toString(); // 'Dog Hellen is a female red Lab'

// 用于进制转换
Number(123).toString(2); // 1111011
Number(9).toString(5); // 14

// 转回 10 进制
parseInt(14, 5); // 9
parseInt(1111011, 2); // 123

valueOf

  • 如果对象存在任意原始值,它就默认将对象转换为示意它的原始值,如果对象是复合值,而且大多数对象无奈真正示意为一个原始值,因而默认的 valueOf() 办法简略地返回对象自身,而不是返回一个原始值。
对象 返回值
Array 数组自身
Boolean 布尔值
Date 返回毫秒模式的工夫戳
Function 函数自身
Number 数字值
Object 对象自身
String 字符串值
// 数组、函数、和正则表达式简略的继承了这个默认办法,调用这些类型的实例的 valueOf() 办法只是简略返回对象自身。// 所有的对象都继承有 toString() 和 valueOf() 办法,对象到字符串,对象到数字的转换,(隐式转换等)会通过调用待转换对象的这两个办法中的一个来实现。// valueOf: 返回对象的原始值示意; toString: 返回对象的字符串示意;
let num = 3;
let str = '3';
let bool = true;
let obj = {test: '123', example: 123};
let func = function () {console.log('example');
};
var arr = ['test', 'example'];

num.valueOf(); // 3
str.valueOf(); // "3"
bool.valueOf(); // true
obj.valueOf(); // {test:'123', example:123}
func.valueOf(); // function () {console.log('example'); }
arr.valueOf(); // ['test','example']
  • 原始值:不可变更的值,包含 undefined、null、boolean、number、string

个别的转换过程

  • 栗子
// 保留原始的 valueOf
const valueOf = Object.prototype.valueOf;
const toString = Object.prototype.toString;
// 增加 valueOf 日志
Object.prototype.valueOf = function () {console.log('调用 valueOf');
  return valueOf.call(this);
};
// 增加 toString 日志
Object.prototype.toString = function () {console.log('调用 toString');
  return toString.call(this);
};

/* ---------- 分割线 ---------- */

let obj = {};
let boolObj = new Boolean(false);
if (obj) {console.log(1);
}
if (boolObj) {console.log(2);
}
// 未调用 valueOf 和 toString,合乎 [对象到布尔值] 的转换规则。/* ---------- 分割线 ---------- */

console.log(++obj);
// 调用 valueOf (先调用了此办法返回的是对象自身,不是原始值,继续执行。)
// 调用 toString (再调用 toString 办法返回的是 "[object Object]",是原始值(字符串)。)
// NaN (将字符串转换为数字,后果变成了 NaN。)

/* ---------- 分割线 ---------- */

let objNum = {};
Object.prototype.valueOf = function () {console.log('调用 valueOf');
  return 1; // 强制返回原始值
};
console.log(++objNum);
// 调用 valueOf
// 2

/* ---------- 分割线 ---------- */

let objTest = {};
alert(objTest);
// 调用 toString
// 弹出 [object Object]
// 对象转字符串,调用 toString 办法,间接返回了字符串 "[object Object]",对象最终转换为该字符串。/* ---------- 分割线 ---------- */

Object.prototype.toString = function () {console.log('调用 toString');
  return {noOriginVal: false};
};
Object.prototype.valueOf = function () {
  // 还原后面的定义
  console.log('调用 valueOf');
  return valueOf.call(this);
};
alert(objTest);
// 调用 toString (调用 toString 办法,返回的不是原始值,继续执行。)
// 调用 valueOf (调用 valueOf 办法,返回的不是原始值,继续执行。)
// Uncaught TypeError: Cannot convert object to primitive value

/* ---------- 分割线 ---------- */

Object.prototype.toString = function () {
  // 还原后面的定义
  console.log('调用 toString');
  return toString.call(this);
};
let newObj = {};
console.log('hello' + newObj);
// 调用 valueOf
// 调用 toString
// 'hello [object Object]'
  • 最初一处本应该是预期把 newObj 当做字符串应用,先调用 toString 办法的,理论状况其实却不是这样。
  1. 【根底步骤】如果有一个是对象,则遵循对象对原始值的转换过程 (Date 对象间接调用 toString 实现转换,其余对象通过 valueOf 转化,如果转换不胜利则调用 toString。)。
  2. 如果两个都是对象,两个对象都遵循【根底步骤】转换到字符串。
  3. 两个数字,进行算数运算。
  4. 两个字符串,间接拼接。
  5. 一个字符串一个数字,间接拼接为字符串。

keys

// 遍历可枚举的属性,只蕴含对象自身可枚举属性,不蕴含原型链可枚举属性。// getOwnPropertyNames 与 keys 类似,但遍历蕴含不可枚举属性。let testObj = {name: 'doubleam', age: 21};
Object.keys(testObj); // ["name", "age"]

values

// 遍历可枚举的属性值,只蕴含对象自身可枚举属性值,不蕴含原型链可枚举属性值。let testObj = {name: 'doubleam', age: 21};
Object.values(testObj); // ["doubleam", 21]

entries

// entries 宰割对象,获取键值对。let testObj = {name: 'doubleam', age: 21};
Object.entries(testObj); // [["name", "doubleam", ["age", 21]]

new Map(Object.entries(testObj)); // Map(2) {"name" => "doubleam", "age" => 21}

is

// Object.is 用来比拟两个值是否严格相等,与严格比拟运算符(===)的行为基本一致,但也有差异。Object.is('test', 'test'); // true
Object.is({}, {}); // false

+0 === -0; //true
NaN === NaN; // false
Object.is(+0, -0); // false
Object.is(NaN, NaN); // true

hasOwnProperty

// Object.hasOwnProperty 办法会返回一个布尔值,示意对象本身属性中是否具备指定的属性,不蕴含原型上的属性。let testObj = {name: 'doubleam', age: 21};
testObj.hasOwnProperty('name'); // true

isPrototypeOf

// 用于测试一个对象是否存在于另一个对象的原型链上
let testObj = {name: 'doubleam', age: 21};
let extendObj = Object.create(testObj, {
  gender: {value: 'man'}
});
testObj.isPrototypeOf(extendObj); // true

propertyIsEnumerable

// 指定的属性是否可枚举
let testObj = {name: 'doubleam', age: 21};
testObj.propertyIsEnumerable('name'); // true
testObj.propertyIsEnumerable('length'); // false 不可枚举属性
testObj.propertyIsEnumerable('toString'); // false 原型属性

defineProperty

// 定义对象属性,Object.defineProperty(object, prop, do)
// 增加属性
let testObj = Object.defineProperty({}, "newProp", {
    value: 1, // 不能与 get set 同时存在
    writable: true, // 不能与 get set 同时存在
    enumerable: true,
    configurable: true // false,不能从新批改装璜器。});
testObj.newProp; // 1

// 批改属性
Object.defineProperty(testObj, "newProp", {writable: false});

// 增加 get set(Vue2 通过此形式进行数据劫持,实现数据监听,但有一些缺点,Vue3 改为 Proxy,后续具体介绍。)let testObj = {otherProp: '1'};
Object.defineProperty(testObj, "newProp", {set: function (value) {this.otherProp = value;},
    get: function () {return this.otherProp;},
    enumerable: true,
    configurable: true
});
testObj.newProp = 3;
testObj.otherProp; // 3

defineProperties

// 同上,但可定义多个。let testObj = {};
Object.defineProperties(testObj, {
  'prop1': {
    value: 'Hello',
    writable: true
  },
  'prop2': {
    value: 'World',
    writable: false
  }
});

工夫(Date)

万能 Date 原型扩大

/* 工夫格局参考 php */
Date.prototype.format = function (fmt = "yyyy-mm-dd hh:ii:ss") {
  let o = {'m+': this.getMonth() + 1, // 获取月份 month 需 + 1
    'd+': this.getDate(), // 获取日
    'h+': this.getHours(), // 获取小时
    'i+': this.getMinutes(), // 获取分钟
    's+': this.getSeconds(), // 获取秒
    'Q+': Math.floor((this.getMonth() + 3) / 3), // 获取季度
    'S': this.getMilliseconds() // 获取毫秒};
  if (/(y+)/.test(fmt)) {fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
  }
  for (let k in o) {if (new RegExp('(' + k + ')').test(fmt)) {fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    }
  }
  return fmt;
};

new Date().format(); // "2020-08-25 23:15:35"
new Date().format('mm-dd hh:ii:ss'); // "08-25 23:15:51"
new Date().format('hh:ii'); // "23:16"
new Date().format('yyyy-mm-01 00:00:00'); // "2020-08-01 00:00:00"

人性化工夫

/**
 * 人性化工夫
 * @param {date|string} date 工夫 /string
 * @param {boolean} longago 是否显示周月甚至更久
 * @param {String} formater 失常显示时的工夫显示格局,依赖于前一个原型办法。* @return {String} 转换后果
 */
function timeSince(date, longago = false, formater = "yyyy-mm-dd hh:ii:ss") {if (!date) {return;}
    date.replace(/-/g, '/'); // 尽管 win 浏览器两种符号都能够,然而需兼容 ios。let dateTS = new Date(date);
  let seconds = Math.floor((new Date() - dateTS) / 1000);
  let interval = Math.floor(seconds / (24 * 3600));
  if (longago) {interval = Math.floor(seconds / (30 * 24 * 3600));
    if (interval >= 4) {return dateTS.format(formater);
    }
    if (interval >= 1) {return interval + "月前";}
    interval = Math.floor(seconds / (7 * 24 * 3600));
    if (interval >= 1) {return interval + "周前";}
  }
  if (interval >= 8) {return dateTS.format(formater);
  }
  interval = Math.floor(seconds / (24 * 3600));
  if (interval >= 1) {return interval + "天前";}
  interval = Math.floor(seconds / 3600);
  if (interval >= 1) {return interval + "小时前";}
  interval = Math.floor(seconds / 60);
  if (interval >= 1) {return interval + "分钟前";}
  return "刚刚";
};

timeSince(new Date()); // "刚刚"

工夫设置与计算

工夫获取能够参考第一局部

let myDate = new Date(); 
myDate.setFullYear(myDate.getFullYear() + 1); // 设置日期,获取 1 年后。[2021/8/25 下午 11:20:35]
myDate.setMonth(myDate.getMonth() - 3); // 设置日期,获取 3 月前。[2021/5/25 下午 11:20:35]
myDate.setDate(myDate.getDate() + 7); // 设置日期,获取 7 天后。[2021/6/1 下午 11:20:35]
myDate.setHours(myDate.getHours() + 10); // 设置日期,获取 10 小时后。[2021/6/2 上午 9:20:35]
myDate.setMinutes(myDate.getMinutes() + 10); // 设置日期,获取 10 分钟后。[2021/6/2 上午 9:30:35]
myDate.setSeconds(myDate.getSeconds() + 60); // 设置日期,获取 60 秒后。[2021/6/2 上午 9:31:35]

+ new Date(); // 1598370615000 疾速获取工夫戳
new Date().getTime(); // 1598370615000

let now = new Date();
let old = new Date("2020-07-25 21:50:15");
let seconds = Math.floor((now - old) / 1000); // 计算工夫相差秒 2685600
let minutes = Math.floor(seconds / 60); // 计算工夫相差分钟 44760
let hours = Math.floor(minutes / 60); // 计算工夫相差小时 746
let days = Math.floor(hours / 24); // 计算工夫相差天数 31

/* 计算理论差距天数、小时、分钟、秒 */
let runTime = now - old;
let differenceObj = {days: Math.floor(runTime / 1000 / 3600 / 24),
  hours: Math.floor(runTime / 1000 / 60 / 60 % 24),
  minutes: Math.floor(runTime / 1000 / 60 % 60),
  seconds: Math.floor(runTime / 1000 % 60)
}; // {days: 31, hours: 2, minutes: 0, seconds: 0}

Others

let weeks = ["星期天", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
weeks[new Date().getDay()]; // 获取星期 0-6

new Date().toLocaleTimeString(); // 获取以后工夫 "下午 5:49:50"

new Date().toLocaleDateString(); // 获取以后日期 "2020/8/25"

// 其余工夫字符串转化
// toJSON() 办法能够将 Date 对象转换为字符串,并格式化为 JSON 数据格式。// JSON 数据用同样的格局就像 x ISO-8601 规范: YYYY-MM-DDThh:ii:ss.sssZ
new Date().toJSON(); // "2020/8/25T23:51:13.411Z"
new Date().toGMTString(); // "Tue, 25 Aug 2020 23:51:20 GMT"
new Date().toISOString(); // "2020/8/25T23:51:13.423Z"
new Date().toUTCString(); // "Tue, 25 Aug 2020 23:51:19 GMT"
new Date().toString(); // "Tue Aug 25 2020 23:51:16 GMT+0800 (中国规范工夫)"
new Date().toTimeString(); // "23:51:13 GMT+0800 (中国规范工夫)"
new Date().toDateString(); // "Tue Aug 25 2020"

new Date().toLocaleString(); // 获取以后日期工夫 "2020/8/25 下午 11:52:23"
new Date().toLocaleString('chinese', { hour12: false}); // 24 小时制 "2020/8/25 23:52:57"
正文完
 0