Typescript&&JavaScript常用笔记
数组
map 循环遍历数组、返回一个新的数组
forEach 循环遍历数组,不改变原数组
push/pop 在数组的末尾添加/删除元素 改变原数组
unshift/ shift 在数组的头部添加/删除元素,改变原数组
join 把数组转化为字符串
some 有一项返回为true,则整体为true
every 有一项返回为true,则整体为false
filter 数组过滤
slice(start, end) 数组截取,包括开头,不包括截取,返回一个新的数组
splice(start, number, value) 删除数组元素,改变原数组
indexof/lastindexof: 查找数组项,返回对应的下标
concat:数组的拼接,不影响原数组,浅拷贝
sort:数组排序 改变原数组
reverse: 数组反转,改变原数组
|
改变原数组的方法(9个):
let a = [1,2,3]; ES5: a.splice()/ a.sort() / a.pop()/ a.shift()/ a.push()/ a.unshift()/ a.reverse() ES6: a.copyWithin() / a.fill
|
splice() 添加/删除数组元素
语法: array.splice(index,howmany,item1,.....,itemX)
参数:
- index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
- howmany:可选。要删除的项目数量。如果设置为 0,则不会删除项目。
- item1, …, itemX: 可选。向数组添加的新项目。
返回值: 如果有元素被删除,返回包含被删除项目的新数组。
eg1:删除元素
let a = [1, 2, 3, 4, 5, 6, 7]; let item = a.splice(0, 3); console.log(a);
let item = a.splice(-1, 3);
|
eg2: 删除并添加
let a = [1, 2, 3, 4, 5, 6, 7]; let item = a.splice(0,3,'添加'); console.log(a);
let b = [1, 2, 3, 4, 5, 6, 7]; let item = b.splice(-2,3,'添加1','添加2'); console.log(b);
|
eg3: 不删除只添加:
let a = [1, 2, 3, 4, 5, 6, 7]; let item = a.splice(0,0,'添加1','添加2'); console.log(a); let b = [1, 2, 3, 4, 5, 6, 7]; let item = b.splice(-1,0,'添加1','添加2'); console.log(b);
|
交集
普通数组
const arr1 = [1,2,3,6,7] const arr2 = [3,6,7,19,22] const result = arr1.filter((e) => arr2.indexOf(e) > -1)
|
数组对象
const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name5', id: 5 }] const arr2 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }] const result = arr2.filter(v => arr1.some(n => JSON.stringify(n) === JSON.stringify(v))) console.log(result)
|
并集
普通数组
const arr1 = [1,2,3,6,7] const arr2 = [3,6,7,19,22] const result = arr1.concat(arr2.filter(e => !arr1.includes(e))) console.log(result)
|
数组对象
const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name5', id: 5 }] const arr2 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }] let arr3 = arr1.concat(arr2); let result = []; let obj = []; result = arr3.reduce(function (prev, cur, index, arr) { obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur); return prev; }, []); console.log(result)
|
去重
普通数组
console.log(Array.from(new Set[1,2,3,3,4])) console.log([...new Set([1,2,3,4,4,4,5])])
|
数组对象
const arr = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }]; const result = []; arr.forEach(item=>{ !result.some(v => JSON.stringify(v) === JSON.stringify(item)) && result.push(item) }) console.log(result)
|
排序
普通数组
console.log([1, 2, 3, 4].sort((a, b) => a - b)); console.log([1, 2, 3, 4].sort((a, b) => b - a));
|
数组对象
const arr1 = [{ name: "Rom", age: 12 }, { name: "Bob", age: 22 }].sort((a, b) => { return a.age - b.age }) const arr2 = [{ name: "Rom", age: 12 }, { name: "Bob", age: 22 }].sort((a, b) => { return -a.age + b.age }) console.log(arr2) console.log(arr1)
|
求和
普通数组
[1, 2, 3, 4].reduce(function (prev, cur) { return prev + cur; }, 0)
|
数组对象
const sum = [{age:1},{age:2}].reduce(function (prev, cur) { return prev + cur.age; }, 0) console.log(sum)
|
合并
普通数组
const arr1 =[1, 2, 3, 4].concat([5, 6]) const arr2 =[...[1, 2, 3, 4],...[4, 5]] const arrA = [1, 2], arrB = [3, 4] const arr3 =[].concat.apply(arrA, arrB)
|
数组对象
const arr4 = [{ age: 1 }].concat([{ age: 2 }]) const arr5 = [...[{ age: 1 }],...[{ age: 2 }]] console.log(arr4) console.log(arr5)
|
对象转数组
Object.keys({ name: '张三', age: 14 }) Object.values({ name: '张三', age: 14 }) Object.entries({ name: '张三', age: 14 }) Object.fromEntries([name, '张三'], [age, 14])
对象转数组1 let obj = {1:'张三', 2:'李四'} let arr = [] for (let index in obj) { arr.push({ 'id': index, 'name': obj[index] }) }
console.dir(arr)
对象转数组2 let obj = {1:'张三', 2:'李四'} let arr = Object.keys(obj).map(index => ({ id: index, name: obj[index]}))
console.dir(arr)
|
数组转对象
数组转对象1 const arr = [1,2,3] const obj = {...arr} 数组转对象2 let arr = [{ id: 1, name: '张三' },{ id: 2, name: '李四' }] let obj = {} arr.forEach(item => obj[item.value] = item.name)
console.dir(obj)
数组转对象3 let arr = [{ id: 1, name: '张三' },{ id: 2, name: '李四' }] let obj = arr.reduce((obj, item) => ({...obj,[item.id]: item.name}), {})
console.dir(obj)
|
数组扁平化
ES6-flat()方法 Infinity展开任意深度的嵌套数组
let arr = [1,2,3,[4,5,6,[7,8]]] console.log('flat', arr.flat(Infinity))
|
JSON.Stringify()\、JSON.parse()
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
let res=JSON.stringify(arr).replace(/\[|\]/g,'')
res=JSON.parse('['+res+']') console.log('parse方法:',res)
|
reduce()方法
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
function flatten(arr){ return arr.reduce((result,item)=>{ return result.concat(Array.isArray(item)?flatten(item):item); },[]) } console.log('reduce方法:',flatten(arr))
const flatten = (list) => [].concat(...list); const flatten = (list) => list.reduce((a, b) => a.concat(b), []);
|
利用扩展运算符[…args]
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
function flatten1(arr) { while (arr.some(item => Array.isArray(item))) { arr = [].concat(...arr) } return arr; } console.log('扩展运算符方法:', flatten1(arr))
|
Split()和toString()
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
function flatten2(arr) { return arr.toString().split(",") } console.log('split和toString方法:', flatten2(arr))
|
递归
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
function flatten3(arr) { let result = [] for (let i = 0; i < arr.length; i++) { if (Array.isArray(arr[i])) { result = result.concat(flatten(arr[i])) console.log(result) } else { result.push(arr[i]) } } return result } console.log('使用递归处理的方法:', flatten2(arr))
|
对象
对象多余属性删除
const { name, age, ...obj } = { name: '张三', age: 13, dec: '描述1', info: '信息' } console.log(name) console.log(age) console.log(obj)
|
对象嵌套属性解构
const { info:{ dec} } = { name: '张三', age: 13, info:{dec: '描述1', info: '信息' }} console.log(dec)
|
对象解构属性别名
const { name:newName } = { name: '张三', age: 13 } console.log(newName)
|
解构对象属性默认值
const { dec='这是默认dec值' } = { name: '张三', age: 13 } console.log(dec)
|
对象转字符串
json.parse()字符串转对象
json.stringify()对象转字符串
qs npm 第三方插件
qs.decode()对象转字符串
qs.encode 字符串转对象
判断两个对象相等
var toString = Object.prototype.toString;
function isFunction(obj) { return toString.call(obj) === '[object Function]' }
function eq(a, b, aStack, bStack) {
if (a === b) return a !== 0 || 1 / a === 1 / b;
if (a == null || b == null) return false;
if (a !== a) return b !== b;
var type = typeof a; if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;
return deepEq(a, b, aStack, bStack); };
function deepEq(a, b, aStack, bStack) {
var className = toString.call(a); if (className !== toString.call(b)) return false;
switch (className) { case '[object RegExp]': case '[object String]': return '' + a === '' + b; case '[object Number]': if (+a !== +a) return +b !== +b; return +a === 0 ? 1 / +a === 1 / b : +a === +b; case '[object Date]': case '[object Boolean]': return +a === +b; }
var areArrays = className === '[object Array]'; if (!areArrays) { if (typeof a != 'object' || typeof b != 'object') return false;
var aCtor = a.constructor, bCtor = b.constructor; if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor && isFunction(bCtor) && bCtor instanceof bCtor) && ('constructor' in a && 'constructor' in b)) { return false; } }
aStack = aStack || []; bStack = bStack || []; var length = aStack.length;
while (length--) { if (aStack[length] === a) { return bStack[length] === b; } }
aStack.push(a); bStack.push(b);
if (areArrays) {
length = a.length; if (length !== b.length) return false;
while (length--) { if (!eq(a[length], b[length], aStack, bStack)) return false; } } else {
var keys = Object.keys(a), key; length = keys.length;
if (Object.keys(b).length !== length) return false; while (length--) {
key = keys[length]; if (!(b.hasOwnProperty(key) && eq(a[key], b[key], aStack, bStack))) return false; } }
aStack.pop(); bStack.pop(); return true;
}
console.log(eq(0, 0)) console.log(eq(0, -0))
console.log(eq(NaN, NaN)); console.log(eq(Number(NaN), Number(NaN)));
console.log(eq('Curly', new String('Curly')));
console.log(eq([1], [1])); console.log(eq({ value: 1 }, { value: 1 }));
var a, b;
a = { foo: { b: { foo: { c: { foo: null } } } } }; b = { foo: { b: { foo: { c: { foo: null } } } } }; a.foo.b.foo.c.foo = a; b.foo.b.foo.c.foo = b;
console.log(eq(a, b))
|
深拷贝
JSON.stringify深度克隆对象;
1.无法对函数 、RegExp等特殊对象的克隆;
2.会抛弃对象的constructor,所有的构造函数会指向Object;
3.对象有循环引用,会报错
实现深拷贝
const _ = require('lodash'); const obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; const obj2 = _.cloneDeep(obj1); console.log(obj1.b.f === obj2.b.f);
const $ = require('jquery'); const obj1 = { a: 1, b: { f: { g: 1 } }, c: [1, 2, 3] }; const obj2 = $.extend(true, {}, obj1); console.log(obj1.b.f === obj2.b.f);
const obj2=JSON.parse(JSON.stringify(obj1));
const obj = { name: 'A', name1: undefined, name3: function() {}, name4: Symbol('A') } const obj2 = JSON.parse(JSON.stringify(obj)); console.log(obj2);
function deepClone(obj, hash = new WeakMap()) { if (obj === null) return obj; if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); if (typeof obj !== "object") return obj; if (hash.get(obj)) return hash.get(obj); let cloneObj = new obj.constructor(); hash.set(obj, cloneObj); for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], hash); } } return cloneObj; }
function deepClone(obj) { if (obj === null) return obj const result = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { if (typeof obj[key] === 'object') { result[key] = deepClone(obj[key]) } else { result[key] = obj[key]; } } } return result; }
|
浅拷贝
实现浅拷贝
function shallowClone (obj) { const newObj = {} for (let prop in obj) { if (obj.hasOwnProperty(prop)) { newObj[prop] = obj[prop]; } } return newObj }
|
其他浅拷贝:
Object.assign(obj1, obj2)
var obj = { age: 18, nature: ['smart', 'good'], names: { name1: 'fx', name2: 'xka' }, love: function () { console.log('fx is a great girl') } } var newObj = Object.assign({}, fxObj); Array.prototype.slice() const fxArr = ["One", "Two", "Three"] const fxArrs = fxArr.slice(0) fxArrs[1] = "love"; console.log(fxArr) console.log(fxArrs)
Array.prototype.concat() const fxArr = ["One", "Two", "Three"] const fxArrs = fxArr.concat() fxArrs[1] = "love"; console.log(fxArr) console.log(fxArrs)
拓展运算符... 相当于浅拷贝 const fxArr = ["One", "Two", "Three"] const fxArrs = [...fxArr] fxArrs[1] = "love"; console.log(fxArr) console.log(fxArrs)
|
闭包的理解
一、是什么?
闭包是让你可以在一个内层函数中访问到其外层函数的作用域
在 JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁
eg:
function init() { var name = "Mozilla"; function displayName() { alert(name); } displayName(); } init();
|
displayName() 没有自己的局部变量。然而,由于闭包的特性,它可以访问到外部函数的变量
二、使用场景
1.任何闭包都离不开两点 创建私有变量 、延长变量的生命周期
断言-非空类型断言
string?
可选为undefined
string!
此处不可能为null/undefined
TypeScript接口
interface Person { name: string; age: number; }
let semlinker: Person = { name: "semlinker", age: 33, };
|
TypeScript 类
类的属性与方法
class Greeter { static cname: string = "Greeter"; greeting: string;
constructor(message: string) { this.greeting = message; }
static getClassName() { return "Class name is Greeter"; }
greet() { return "Hello, " + this.greeting; } }
let greeter = new Greeter("world");
|
编译生成的ES5代码
"use strict"; var Greeter = (function () { function Greeter(message) { this.greeting = message; } Greeter.getClassName = function () { return "Class name is Greeter"; }; Greeter.prototype.greet = function () { return "Hello, " + this.greeting; }; Greeter.cname = "Greeter"; return Greeter; }()); var greeter = new Greeter("world");
|
TypeScript泛型
泛型(Generics)是允许同一个函数接受不同类型参数的一种模板。相比于使用 any 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。

泛型接口
interface GenericIdentityFn<T> { (arg: T): T; }
|
泛型类
class GenericNumber<T> { zeroValue: T; add: (x: T, y: T) => T; }
let myGenericNumber = new GenericNumber<number>(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; };
|
泛型工具类型
Partial
Partial<T>`的作用就是将某个类型里的属性全部变为可选项`?
|
keyof
keyof可以用来取得一个对象接口的所有key值
interface Foo { name: string; age: number; }
type T = keyof Foo // => "name" | "age" const x: T = "name" // ok const y: T = "test" // 报错
|
in
in 是可以遍历枚举类型
type T = 'a' | 'b' type Obj = { [p in T]: any } // => { a: any, b: any }
|
keyof产生枚举类型,in使用枚举类型遍历, 所以他们经常一起使用
interface Person { name: string; age: number; interest: string; }
type T = Partial<Person > T => { name?: string; age?: number; interest?: string; }
|
Required
interface IRead { name?: string; age?: number; interest?: string; } type T = Required<IRead > T => { name: string; age: number; interest: string; }
|
Pick
Pick 的作用是将某个类型中的子属性挑出来,变成包含这个类型部分属性的子类型。
interface Person { name: string; age: number; interest: string; }
type T = Pick<Person, 'name' | 'age'> T => { name: string; age: number;}
|
Exclude
Exclude<T, U>的作用是将某个类型中属于另一个的类型移除掉。
type Exclude<T, U> = T extends U ? never : T;
|
如果T能赋值给U类型的话,那么就会返回never类型,否则返回T类型。最终实现的效果就是将T中某些属于U的类型移除掉。
type T = Exclude<'a' | 'b', 'a'> T => 'b' type T2 = Exclude<'a' | 2 | 'c', 'c'> T2 => 'a' | 2
|
ReturnType
ReturnType<T>的作用是用于获取函数T的返回类型。
function foo(age: number): number { return age }
type T = ReturnType< typeof foo> const res: T = 20
|
Record<K, T>
类型参数K提供了对象属性名联合类型,类型参数T提供了对象属性的类型
interface Person { name: string; }
type Peoples = Record<"x" | "y", Person>;
const P: Peoples = { x: { name: '张三' }, y: { name: '李四' } }
|
Omit<T, K>
在 T 中删除对应的 K
interface IPerson { name: string; age: number; }
type TP = Omit<IPerson, 'age'>;
const p: TP = { name: '张三' }
|
TypeScript 装饰器
什么是装饰器?
·它是一个表达式,被执行后返回一个函数
·函数的入参分别为 target、name 和 descriptor
·执行该函数后,可能返回descriptor对象,用于配置target对象。
装饰器分类
…..暂时还不理解这一层。
TypeScript编译上下文
tsconfig.json 的作用
- 用于标识 TypeScript 项目的根路径;
- 用于配置 TypeScript 编译器;
- 用于指定编译的文件
tsconfig.json 重要字段
- files - 设置要编译的文件的名称;
- include - 设置需要进行编译的文件,支持路径模式匹配;
- exclude - 设置无需进行编译的文件,支持路径模式匹配;
- compilerOptions - 设置与编译流程相关的选项。
compilerOptions 选项
{ "compilerOptions": {
"target": "es5", "module": "commonjs", "lib": [], "allowJs": true, "checkJs": true, "jsx": "preserve", "declaration": true, "sourceMap": true, "outFile": "./", "outDir": "./", "rootDir": "./", "removeComments": true, "noEmit": true, "importHelpers": true, "isolatedModules": true,
"strict": true, "noImplicitAny": true, "strictNullChecks": true, "noImplicitThis": true, "alwaysStrict": true,
"noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true,
"moduleResolution": "node", "baseUrl": "./", "paths": {}, "rootDirs": [], "typeRoots": [], "types": [], "allowSyntheticDefaultImports": true,
"sourceRoot": "./", "mapRoot": "./", "inlineSourceMap": true, "inlineSources": true,
"experimentalDecorators": true, "emitDecoratorMetadata": true } }
|
开发问题集锦
string? 可选为undefined
string!变量后使用表示推断排除null/undefined
json.parse()字符串转对象
json.stringify()对象转字符串
qs npm 第三方插件
qs.decode()对象转字符串
qs.encode 字符串转对象
数组去重function unique(arr) {
if (!Array.isArray(arr)) {
console.log(“type error!”);
return;
}
return Array.from(new Set(arr));
}
数组转对象1
const arr = [1,2,3]
const obj = {…arr}
数组转对象2
let arr = [{ id: 1, name: ‘张三’ },{ id: 2, name: ‘李四’ }]
let obj = {}
arr.forEach(item => obj[item.value] = item.name)
console.dir(obj)
/*
Object
1: “张三”
2: “李四”
*/
数组转对象3
let arr = [{ id: 1, name: ‘张三’ },{ id: 2, name: ‘李四’ }]
let obj = arr.reduce((obj, item) => ({…obj,[item.id]: item.name}), {})
console.dir(obj)
/*
Object
1: “张三”
2: “李四”
*/
对象转数组1
let obj = {1:’张三’, 2:’李四’}
let arr = []
for (let index in obj) {
arr.push({
‘id’: index,
‘name’: obj[index]
})
}
console.dir(arr)
/*
Array(2)
0: {id: ‘1’, name: ‘张三’}
1: {id: ‘2’, name: ‘李四’}
length: 2
*/
对象转数组2
let obj = {1:’张三’, 2:’李四’}
let arr = Object.keys(obj).map(index => ({ id: index, name: obj[index]}))
console.dir(arr)
/*
Array(2)
0: {id: ‘1’, name: ‘张三’}
1: {id: ‘2’, name: ‘李四’}
length: 2
*/
css动画显隐.show {
opacity: 1;
transition-duration: 0.2s;
-ms-transform: scale(1);
transform: scale(1);
overflow-x: hidden;
overflow-y: auto;
pointer-events: auto;
}
遍历tree树形结构改变key值
mapTree(org) {
const haveChildren = org.children && Array.isArray(org.children) && org.children.length > 0;
return {
//改变他的key
label: org.name,
value: org.id,
// data: { …org },
//判断它是否存在子集,若果存在就进行再次进行遍历操作
children: haveChildren ? org.children.map(i => this.mapTree(i)) : null
};
},
getCategoryList() {
getCategory().then(res => {
if (Array.isArray(res.data.data)) {
this.options = res.data.data.map(org => this.mapTree(org));
}
}).catch(() => { })
},
一维数组转树形
var list = [
{ id: 1, name: “冰箱”, pid: “” },
{ id: 2, name: “海尔冰箱”, pid: 1 },
{ id: 3, name: “美的冰箱”, pid: 1 },
{ id: 4, name: “电视”, pid: “” },
{ id: 5, name: “小米电视”, pid: 4 },
];
var list1 = []
list.forEach(function (item) {
if (item.pid === “”) {
item.children = []
list1.push(item)
list.forEach((item1) => {
if (item1.pid == item.id) {
item.children.push(item1)
}
})
}
})
console.log(list1)
文本换行 回车
white-space:pre-wrap;
word-break: break-all;
文字省略号.text-container {
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2; /* 设置最大显示行数 */
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}或
行内元素隐藏
width: 200px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
弧形背景
:root {
–main-bg-color: #FFFFFF;
}
.grade_container {
height: 330rpx;
}
.container .grade_container .bg_color {
width:100%;
padding-top: 30rpx;
height: 330rpx;
position: relative;
overflow-x: hidden;
z-index: 1;
}
.container .grade_container .bg_color::after {
content: “”;
display: block;
width: 120%;
height: 200rpx;
position: absolute;
left: -10%;
top: 0;
z-index: -1;
border-radius: 0 0 70% 70%;
background-color: var(–main-bg-color);
}
笛卡称积可以写的更简单。
arr.reduce((a, b) => {
return a.flatMap(x => b.map(y => […x, y]))},
[[]]
)