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); //10let 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); // 6console.log(testArr); // [1,2,3,4,5,6]
pop
// pop 办法用于删除并返回数组的最初一个元素,扭转原数组。let testArr = [1, 2, 3, 4];testArr.pop(); // 4console.log(testArr); // [1,2,3]
shift
// shift 办法用于把数组的第一个元素从其中删除,并返回第一个元素的值,扭转原数组。let testArr = [1, 2, 3, 4];testArr.shift(); // 1console.log(testArr); // [2,3,4]
unshift
// unshift 办法可向数组的结尾增加一个或更多元素,并返回新的长度,扭转原数组。let testArr = [1, 2, 3, 4];testArr.unshift(-1, 0); // 6console.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); // 0testArr.lastIndexOf(1); // 3testArr.indexOf(4); // -1
find
// find 和 findIndex 传入一个回调函数,找到数组中合乎以后搜寻规定的第一个元素,返回它,并且终止搜寻。findIndex 返回的是下标。let testArr = [1, 2, 3, 4];testArr.find((item, index, selfArray) => item > 1); // 2testArr.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'}// Setlet testSet = new Set(['a', 'b', 'c']);for(let value of testSet.values()) { console.log(value); // 'a' 'b' 'c'}// Maplet 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'}// Setlet testSet = new Set(['a', 'b', 'c']);for(let value of testSet.keys()) { console.log(value); // 'a' 'b' 'c'}// Maplet 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); // truetestArr.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 实现 newfunction 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,nullObject.assign(target, undefined) === target; // trueObject.assign(target, null) === target; // trueObject.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); // 1111011Number(9).toString(5); // 14// 转回 10 进制parseInt(14, 5); // 9parseInt(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(); // 3str.valueOf(); // "3"bool.valueOf(); // trueobj.valueOf(); // {test:'123', example:123}func.valueOf(); // function () { console.log('example'); }arr.valueOf(); // ['test','example']
- 原始值:不可变更的值,包含
undefined、null、boolean、number、string
。
个别的转换过程
// 保留原始的 valueOfconst 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 办法的,理论状况其实却不是这样。
- 【根底步骤】如果有一个是对象,则遵循对象对原始值的转换过程 (Date对象间接调用 toString 实现转换,其余对象通过 valueOf 转化,如果转换不胜利则调用 toString。)。
- 如果两个都是对象,两个对象都遵循【根底步骤】转换到字符串。
- 两个数字,进行算数运算。
- 两个字符串,间接拼接。
- 一个字符串一个数字,间接拼接为字符串。
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'); // trueObject.is({}, {}); // false+0 === -0; //trueNaN === NaN; // falseObject.is(+0, -0); // falseObject.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'); // truetestObj.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(); // 1598370615000let now = new Date();let old = new Date("2020-07-25 21:50:15");let seconds = Math.floor((now - old) / 1000); // 计算工夫相差秒 2685600let minutes = Math.floor(seconds / 60); // 计算工夫相差分钟 44760let hours = Math.floor(minutes / 60); // 计算工夫相差小时 746let 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-6new Date().toLocaleTimeString(); // 获取以后工夫 "下午5:49:50"new Date().toLocaleDateString(); // 获取以后日期 "2020/8/25"// 其余工夫字符串转化// toJSON() 办法能够将 Date 对象转换为字符串,并格式化为 JSON 数据格式。// JSON 数据用同样的格局就像x ISO-8601 规范: YYYY-MM-DDThh:ii:ss.sssZnew 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"