无聊的知识又增加了

hasOwnProperty()

hasOwnProperty()方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(是否有指定的键)

const obj = {
  a: 1,
  b: 2,
};
console.log(obj.hasOwnProperty('a'), obj.hasOwnProperty('c')); // true false

TypeScript

  1. TS 类型
  • 布尔类型(Boolean)
  • const flag:boolean = true;
  • 数值类型(Number)
  • const num:number = 233;
  • 字符串类型(String)
  • const str:string = ‘abc’;
  • 枚举类型(Enum)
// 普通枚举 初始值默认为 0 其余的成员会会按顺序自动增长 可以理解为数组下标
enum Color {
    RED,
    PINK,
    BLUE,
}

const pink: Color = Color.PINK;
console.log(pink); // 1

// 设置初始值
enum Color {
    RED = 10,
    PINK,
    BLUE,
}
const pink: Color = Color.PINK;
console.log(pink); // 11

// 字符串枚举
enum Color {
    RED = "红色",
    PINK = "粉色",
    BLUE = "蓝色",
}

const pink: Color = Color.PINK;
console.log(pink); // 粉色

// 常量枚举 它是使用 const 关键字修饰的枚举,常量枚举与普通枚举的区别是,整个枚举会在编译阶段被删除 我们可以看下编译之后的效果

const enum Color {
    RED,
    PINK,
    BLUE,
}

const color: Color[] = [Color.RED, Color.PINK, Color.BLUE];

//编译之后的js如下:
var color = [0 /* RED */, 1 /* PINK */, 2 /* BLUE */];
// 可以看到我们的枚举并没有被编译成js代码 只是把color这个数组变量编译出来
  • 数组类型(Array)
  • const arr:number[]= [1,2,3];
  • const arr2:number=[1,2,3];
  • 元组类型(tuple)
  • 在 TypeScript 的基础类型中,元组( Tuple )表示一个已知数量和类型的数组 其实可以理解为他是一种特殊的数组
  • const arr:[string,number] = [‘abc’,123];
  • Symbol
  • Symbol 值表示唯一不变的值
  • const flag1 = Symbol(‘abc’);
  • const flag2 = Symbol(‘abc’);
  • console.log(flag1 === flag2);// false
  • 任意类型(any)
  • 任何类型都可以被归为 any 类型,实际上大部分情况下我们都不应该声明 any 类型,但是对于那些在编译阶段我们不清楚的类型变量指定一个类型,比如那些来自于动态的,用户输入的或者第三方的。
  • const ele:any = ‘abcd’;
  • null 和 undefined
  • const a:undefined = undefined;
  • const b:null = null;
  • 空类型(void)
  • void 表示没有任何类型 当一个函数没有返回值时 TS 会认为它的返回值是 void 类型
  • function myName(name: string): void {}
  • never 类型
  • never 一般表示用户无法达到的类型 例如 never 类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型
  • function neverReach(): never {
    throw new Error(“an error”);
    }
  • 大数值类型(BigInt)
const max1 = Number.MAX_SAFE_INTEGER; // 2**53-1
console.log(max1 + 1 === max1 + 2); //true

const max2 = BigInt(Number.MAX_SAFE_INTEGER);
console.log(max2 + 1n === max2 + 2n); //false

let foo: number;
let bar: bigint;
foo = bar; //error
bar = foo; //error
  • 类型推断
  • const flag; // any
  • const str = ‘abc’;// string
  • const num = 12;// number
  • 联合类型
  • 联合类型(Union Types)表示取值可以为多种类型中的一种
  • const age:string|number
  • 类型断言
  • 手动告诉 ts 就按照你断言的那个类型通过编译
  • 尖括号语法:const strLen:number = (strValue).length
  • as 语法:const strLen:number =(strValue as string).length
  • 非空断言:上下文中当类型检查器无法断定类型时 一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型
  • let flag: null | undefined | string;
  • flag!.toString(); // ok
  • flag.toString(); // error
  • 字面量类型
  • 在 TypeScript 中,字面量不仅可以表示值,还可以表示类型,即所谓的字面量类型。
    目前,TypeScript 支持 3 种字面量类型:字符串字面量类型、数字字面量类型、布尔字面量类型,对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型
  • const flag :‘abc’ = ‘abc’;
  • 类型别名
  • 类型别名用来给某个类型取一个新名字
  • const newType = string | number
  • const name:newType = ‘lucy’
  • 交叉类型
  • 交叉类型可将多种类型合并为一种类型,用&运算符实现
  • type f1 = {x:string}
  • type f2 = {y:number} & f1
  1. 函数
  • 指定函数参数和返回值的类型
function myName(name: string): void {
  console.log(name);
}
  • 定义函数类型
type sumFunc = (x: number, y: number) => number;

let countNum: sumFunc = function (a, b) {
  return a + b;
};
  • 可选参数和默认参数
function print(name: string = 'tom', age?: number): void {
  console.log(name, age);
}
print('Lucy');
  • 剩余参数
function sum(...numbers: number[]) {
  return numbers.reduce((val, item) => (val += item), 0);
}
console.log(sum(1, 2, 3));
  • 函数重载
  • 函数重载或方法重载是使用相同名称和不同参数数量或类型创建多个方法的一种能力。 在 TypeScript 中,表现为给同一个函数提供多个函数类型定义
let obj: any = {};
function attr(val: string): void;
function attr(val: number): void;
function attr(val: any): void {
  if (typeof val === 'string') {
    obj.name = val;
  } else {
    obj.age = val;
  }
}
attr('Lucy');
attr(9);
attr(true);
console.log(obj);

注意:函数重载真正执行的是同名函数最后定义的函数体 在最后一个函数体定义之前全都属于函数类型定义 不能写具体的函数实现方法 只能定义类型;

注意重写和重载的区别,重写是子类重写继承于父类的方法,重载是对同一个函数提供多个类型定义

  1. 其他
  • readonly 只读属性
  • readonly 修饰的变量只能在构造函数中初始化 TypeScript 的类型系统同样也允许将 interface、type、 class 上的属性标识为 readonly
interface {
   readonly name:string
}
  1. 接口(interface)
  • 接口既可以在面向对象编程中表示为行为的抽象,也可以描述对象的形状,我们用接口来定义对象的类型
interface selfType {
  name: string;
  age?: number; // 可选属性
  speaks(): void; // 方法定义
  readonly sex: string; // 只读属性
  [propsName: string]: any; // 任意属性
}
  • 接口继承
interface a {
  myName(): void;
}
interface b extends a {
  sayName(): void;
}
  • 接口的重复定义
interface a {
  name: string;
}
interface a {
  age: number;
}
// 重复定义的接口会被自动合并成为一个接口
  1. 泛型
  • 有时候我们希望一个组件能够支持多种类型的数据,并且能够使得传入的参数和返回的参数和我们期望的能够一致
//不用泛型,我们可能需要这样定义:
function myName(name: string): string {
  return name;
}
// 或者改成any来定义
function myName(name: any): any {
  return name;
}
// 但是这样定义会丢失一些信息,我们只知道这个函数可以传入任意类型的参数,但是如果我们传入一个数字,那么返回值的类型可能是任意的
// 此时就需要泛型来定义了
function myName<T>(name: T): T {
  return name;
}
// T会帮助我们捕获传入的值,之后在使用这个类型,那么这里我们就能够使得传入参数和返回是同样的类型了
  • 多个类型参数和泛型约束以及默认类型
  • 如果我们需要有多个未知的类型,那么我们可以定义多个不同的字母来表示不同的类型参数
  • 在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法,这个时候需要进行泛型约束
  • 可以为泛型中的类型参数指定默认类型。当使用泛型时没有在代码中直接指定类型参数,实际值参数中也无法推测出时,使用这个默认类型
interface a {
  name: string;
}
function myName<T = number, U extends a>(arr: [T, U]): [U, T] {
  return [arr[1], arr[0]];
}

myName([20, 'Lucy']); // ['Lucy', 20]

这里的 extends 代表泛型约束,和类里面的继承有区别

  • 泛型接口
  • 定义接口时指定泛型
interface Cart<T> {
  list: T[];
}
let cart: Cart<{ name: string; price: number }> = {
  list: [{ name: 'hello', price: 10 }],
};
console.log(cart.list[0].name, cart.list[0].price);
  • 工具类型
  • Exclude<T,U> 从 T 可分配的类型中排除 U
type Exclude<T, U> = T extends U ? never : T;
type E = Exclude<string | number, string>;
let a: E = 10;
  • Extract<T,U> 从 T 可分配的类型中提取 U
type Extract<T, U> = T extends U ? T : never;
type E = Extract<string | number, string>;
let a: E = '1';
  • Partial Partial 可将传入的属性由必须变为可选
interface A {
  a: string;
  b: number;
  c: boolean;
}
type aPartial = Partial<A>;
const d: aPartial = {};
  • Required Required 可将传入的属性中的可选项变为必选项
interface Person {
  name: string;
  age: number;
  gender?: 'male' | 'female';
}
let p: Required<Person> = {
  name: 'hello',
  age: 10,
  gender: 'male',
};
  • Readonly Readonly 为传入的属性每一项都加上 readonly
interface Person {
  name: string;
  age: number;
  gender?: 'male' | 'female';
}
let p: Readonly<Person> = {
  name: 'hello',
  age: 10,
  gender: 'male',
};
p.age = 15; // error,只读,不可改变
  • Pick<T,U> Pick 能够从传入的属性中获取某些返回
interface toA {
  title: string;
  desc: string;
  id: number;
}
type toB = Pick<toA, 'title' | 'desc'>;
// 相当于下面这个
type toB = {
  title: string;
  desc: string;
};
  1. 文件声明
  • 可以把类型声明单独放在一个类型声明文件里面
  • 文件命名为 fileName.d.ts
declare interface NameList {
  id: number;
  name: string;
}

js 实践小方法

// 生产随机字符串
export const genRandomStr = (): string => {
  return Math.random().toString(36).substr(2, 10);
};

// 数据类型判断
export const checkDataType: (arg0: any) => string = (data) => {
  return Object.prototype.toString.call(data).slice(8, -1);
};

// 随机颜色-十六进制,并过滤指定颜色,指定输入六位十六进制数组,ex:['#cccccc']
export const getRandomColor = (filterColor?: string[]): string => {
  /* 使用js时需要加上如下判断 */
  // if (filterColor && checkDataType(filterColor) !== 'Array') {
  //   throw new Error('Incorrect input!');
  // }
  if (filterColor && filterColor.length) {
    /* TS这里无需校验是否数组 */
    // if (filterColor && checkDataType(filterColor) === 'Array' && filterColor.length) {
    filterColor.map((item) => {
      if (item.length !== 7) {
        throw new Error('There is an incorrect color value');
      }
      return item;
    });
  }

  let colors = '#';
  for (let i = 0; i < 6; i++) {
    colors += Math.floor(Math.random() * 16).toString(16);
  }
  if (filterColor && filterColor.length && filterColor.includes(colors)) {
    return getRandomColor(filterColor);
  }
  return colors;
};

less

  1. 变量
/*定义*/
@width: 10px;
@aColor: red;
/*进阶用法*/
@property: color;
--theme-color: #ccc;
.box {
  @{property}: var(--theme-color);
  background-@{property}: white;
}
// 相当于
.box {
  color: @ccc;
  background-color: white;
}
  1. 混合(mixins)
/* 定义 */
.borders {
  border: dotted 1px black;
}
/* 使用 */
a {
  .borders();
}
/*带参混合*/
.custom_border(@bd:1px) {
  // 可以设置默认值
  border: solid @bd #ccc;
}
/*使用*/
a {
  .border(2px);
}
// 针对多个值,可以使用arguments一键设置
.custom_padding(@up,@right,@down,@left) {
  padding: @arguments;
}
.box {
  .custom_padding(30px,10px,30px,30xp);
}
// 相当于
.box {
  padding: 30px 10px 30px 30px;
}
  1. 嵌套
  2. 运算
width: 10 + 20px; // result:30px
@base: 10%;
width: 10% + @base; // result:20%
  1. 函数
  2. 命名空间和访问符
  3. 映射(Maps)
#colors() {
  primary: blue;
  secondary: green;
}
.button {
  color: #colors[primary];
  border: 1px solid #colors[secondary];
}
  1. 作用域(Scope)
  • Less 中的作用域与 CSS 中的作用域非常类似。首先在本地查找变量和混合(mixins),如果找不到,则从“父”级作用域继承
@var: red;
#page {
  #header {
    color: @var; // white
  }
  @var: white;
}
  1. 注释(comments)
  • 块注释和行注释均可(css 里面不支持行注释)
/* 一个块注释
* style comment! */
@var: red;

// 这是行注释
@var: white;

其他

npm root -g 查看 npm 软件包安装在全局的位置
npm view versions 查看某个包的所有可使用版本