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)

参数:

  1. index:必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
  2. howmany:可选。要删除的项目数量。如果设置为 0,则不会删除项目。
  3. item1, …, itemX: 可选。向数组添加的新项目。

返回值: 如果有元素被删除,返回包含被删除项目的新数组。

eg1:删除元素

let a = [1, 2, 3, 4, 5, 6, 7];
let item = a.splice(0, 3); // [1,2,3]
console.log(a); // [4,5,6,7]
// 从数组下标0开始,删除3个元素
let item = a.splice(-1, 3); // [7]
// 从最后一个元素开始删除3个元素,因为最后一个元素,所以只删除了7

eg2: 删除并添加

 let a = [1, 2, 3, 4, 5, 6, 7];
let item = a.splice(0,3,'添加'); // [1,2,3]
console.log(a); // ['添加',4,5,6,7]
// 从数组下标0开始,删除3个元素,并添加元素'添加'
let b = [1, 2, 3, 4, 5, 6, 7];
let item = b.splice(-2,3,'添加1','添加2'); // [6,7]
console.log(b); // [1,2,3,4,5,'添加1','添加2']
// 从数组最后第二个元素开始,删除3个元素,并添加两个元素'添加1'、'添加2'

eg3: 不删除只添加:

let a = [1, 2, 3, 4, 5, 6, 7];
let item = a.splice(0,0,'添加1','添加2'); // [] 没有删除元素,返回空数组
console.log(a); // ['添加1','添加2',1,2,3,4,5,6,7]
let b = [1, 2, 3, 4, 5, 6, 7];
let item = b.splice(-1,0,'添加1','添加2'); // [] 没有删除元素,返回空数组
console.log(b); // [1,2,3,4,5,6,'添加1','添加2',7] 在最后一个元素的前面添加两个元素

交集

普通数组

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) // [{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name5', id: 5 }]
// 利用JSON.stringify转成对象 判断对象属性

并集

普通数组

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) //[1, 2, 3, 6, 7, 19, 22]

数组对象

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) //[{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]

排序

普通数组

console.log([1, 2, 3, 4].sort((a, b) => a - b)); // [1, 2,3,4] 升序
console.log([1, 2, 3, 4].sort((a, b) => b - a)); // [4,3,2,1] 降序

数组对象

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) // [{ name: 'Bob', age:22 }, { name: 'Rom', age: 12 }]
console.log(arr1) // [ { name: 'Rom', age: 12 }, { name: 'Bob', age: 22 } ]

求和

普通数组

[1, 2, 3, 4].reduce(function (prev, cur) {
return prev + cur;
}, 0) //10

数组对象

const sum = [{age:1},{age:2}].reduce(function (prev, cur) {
return prev + cur.age;
}, 0) //3
console.log(sum)

合并

普通数组

const arr1 =[1, 2, 3, 4].concat([5, 6]) //[1,2,3,4,5,6]
const arr2 =[...[1, 2, 3, 4],...[4, 5]] //[1,2,3,4,5,6]
const arrA = [1, 2], arrB = [3, 4]
const arr3 =[].concat.apply(arrA, arrB)//arrA值为[1,2,3,4]

数组对象

const arr4 = [{ age: 1 }].concat([{ age: 2 }])
const arr5 = [...[{ age: 1 }],...[{ age: 2 }]]
console.log(arr4) //[ { age: 1 }, { age: 2 } ]
console.log(arr5) // [ { age: 1 }, { age: 2 } ]

对象转数组

Object.keys({ name: '张三', age: 14 }) //['name','age']
Object.values({ name: '张三', age: 14 }) //['张三',14]
Object.entries({ name: '张三', age: 14 }) //[[name,'张三'],[age,14]]
Object.fromEntries([name, '张三'], [age, 14]) //ES10的api,Chrome不支持 , firebox输出{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)
/*
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
*/

数组转对象

数组转对象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: "李四"
*/

数组扁平化

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 ] ] ] 
//1.先定义一个数组
//方法二:JSON.stringify,JSON.parse方法
let res=JSON.stringify(arr).replace(/\[|\]/g,'')
// 过滤所有的中中括号
res=JSON.parse('['+res+']')
console.log('parse方法:',res)

reduce()方法

//1.先定义一个数组
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
//方法三:reduce方法
function flatten(arr){
return arr.reduce((result,item)=>{
return result.concat(Array.isArray(item)?flatten(item):item);
// 如果元素是数组,数组的结果通过数组的 concat 方法拼接到最后要返回的 result 数组
},[])
}
console.log('reduce方法:',flatten(arr))

// 法2
const flatten = (list) => [].concat(...list);
const flatten = (list) => list.reduce((a, b) => a.concat(b), []);

利用扩展运算符[…args]

//1.先定义一个数组
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
//方法四:利用扩展运算符
function flatten1(arr) {
// 只要arr数组中还存在数组元素,循环就继续进行
while (arr.some(item => Array.isArray(item))) {
// 展开数组,拼接空数组
arr = [].concat(...arr)
}
return arr;
}
console.log('扩展运算符方法:', flatten1(arr))

Split()和toString()

//1.先定义一个数组
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
//方法五:split和toString()方法共同处理
function flatten2(arr) {
// toString()方法把数组转换为1,2,3,4,5
return arr.toString().split(",")
}
console.log('split和toString方法:', flatten2(arr))

递归

//1.先定义一个数组
let arr=[ 1 , 2 , [ 3 , 4 , [ 5 , 6 ] ] ]
//方法六:递归
function flatten3(arr) {
let result = []
for (let i = 0; i < arr.length; i++) {
// 如果元素是数组,数组的结果通过数组的 concat 方法拼接到最后要返回的 result 数组
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) // 13
console.log(obj) // {dec: '描述1', info: '信息' }

对象嵌套属性解构

const { info:{ dec} } = { name: '张三', age: 13, info:{dec: '描述1', info: '信息' }}
console.log(dec) // 描述1

对象解构属性别名

const { name:newName } = { name: '张三', age: 13 }
console.log(newName) // 张三

解构对象属性默认值

const { dec='这是默认dec值' } = { name: '张三', age: 13 }
console.log(dec) //这是默认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) {

// === 结果为 true 的区别出 +0 和 -0
if (a === b) return a !== 0 || 1 / a === 1 / b;

// typeof null 的结果为 object ,这里做判断,是为了让有 null 的情况尽早退出函数
if (a == null || b == null) return false;

// 判断 NaN
if (a !== a) return b !== b;

// 判断参数 a 类型,如果是基本类型,在这里可以直接返回 false
var type = typeof a;
if (type !== 'function' && type !== 'object' && typeof b != 'object') return false;

// 更复杂的对象使用 deepEq 函数进行深度比较
return deepEq(a, b, aStack, bStack);
};

function deepEq(a, b, aStack, bStack) {

// a 和 b 的内部属性 [[class]] 相同时 返回 true
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;
// aCtor 和 bCtor 必须都存在并且都不是 Object 构造函数的情况下,aCtor 不等于 bCtor, 那这两个对象就真的不相等啦
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)) // true
console.log(eq(0, -0)) // false

console.log(eq(NaN, NaN)); // true
console.log(eq(Number(NaN), Number(NaN))); // true

console.log(eq('Curly', new String('Curly'))); // true

console.log(eq([1], [1])); // true
console.log(eq({ value: 1 }, { value: 1 })); // true

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)) // true

深拷贝

JSON.stringify深度克隆对象;
1.无法对函数 、RegExp等特殊对象的克隆;
2.会抛弃对象的constructor,所有的构造函数会指向Object;
3.对象有循环引用,会报错

​ 实现深拷贝

const _ = require('lodash'); // lodash JavaScript常用函数库
const obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
const obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false

/*******************jQuery.extend()********************/
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); // false

/****************JSON.stringify()***********************/
const obj2=JSON.parse(JSON.stringify(obj1));
// JSON.stringify()会忽略undefined、symbol和函数
const obj = {
name: 'A',
name1: undefined,
name3: function() {},
name4: Symbol('A')
}
const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // {name: "A"}

/********************递归实现深克隆***********************/
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
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();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
// 递归2深克隆,有null情况
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() // slice
const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.slice(0)
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
/**********************************************/
Array.prototype.concat() // concat
const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.concat()
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
/**********************************************/
拓展运算符... 相当于浅拷贝
const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
/**********************************************/

闭包的理解

一、是什么?

闭包是让你可以在一个内层函数中访问到其外层函数的作用域

JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来,作为函数内部与外部连接起来的一座桥梁

eg:

function init() {
var name = "Mozilla"; // name 是一个被 init 创建的局部变量
function displayName() { // 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 = /** @class */ (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 类型,使用泛型来创建可复用的组件要更好,因为泛型会保留参数类型。

img

泛型接口

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

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;
}

// 将x, y 作为Person的key
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对象。

装饰器分类

  • 类装饰器(Class decorators)
  • 属性装饰器(Property decorators)
  • 方法装饰器(Method decorators)
  • 参数装饰器(Parameter decorators)

…..暂时还不理解这一层。

TypeScript编译上下文

tsconfig.json 的作用

  • 用于标识 TypeScript 项目的根路径;
  • 用于配置 TypeScript 编译器;
  • 用于指定编译的文件

tsconfig.json 重要字段

  • files - 设置要编译的文件的名称;
  • include - 设置需要进行编译的文件,支持路径模式匹配;
  • exclude - 设置无需进行编译的文件,支持路径模式匹配;
  • compilerOptions - 设置与编译流程相关的选项。

compilerOptions 选项

{
"compilerOptions": {

/* 基本选项 */
"target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"lib": [], // 指定要包含在编译中的库文件
"allowJs": true, // 允许编译 javascript 文件
"checkJs": true, // 报告 javascript 文件中的错误
"jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
"declaration": true, // 生成相应的 '.d.ts' 文件
"sourceMap": true, // 生成相应的 '.map' 文件
"outFile": "./", // 将输出文件合并为一个文件
"outDir": "./", // 指定输出目录
"rootDir": "./", // 用来控制输出目录结构 --outDir.
"removeComments": true, // 删除编译后的所有的注释
"noEmit": true, // 不生成输出文件
"importHelpers": true, // 从 tslib 导入辅助工具函数
"isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).

/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"strictNullChecks": true, // 启用严格的 null 检查
"noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
"alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'

/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)

/* 模块解析选项 */
"moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"baseUrl": "./", // 用于解析非相对模块名称的基目录
"paths": {}, // 模块名到基于 baseUrl 的路径映射的列表
"rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
"typeRoots": [], // 包含类型声明的文件列表
"types": [], // 需要包含的类型声明文件名列表
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。

/* Source Map Options */
"sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
"mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
"inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
"inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性

/* 其他选项 */
"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]))},
[[]]
)