TypeScript语法

  • 基础语法
    • 基础类型和对象类型
    • 类型注解和类型推断
    • 函数相关类型
    • 数组与元组
    • Interface接口
    • 类和类的继承
    • 类中的访问类型和构造器
    • 静态属性、setter和getter
    • 抽象类
  • 进阶语法
    • TypeScript中的配置文件
    • 联合类型和类型保护
    • Enum枚举类型
    • 泛型
      • 函数中的泛型
      • 类中的泛型
      • 泛型中keyof的用法
  • 高级语法
    • 类的装饰器
    • 方法装饰器
    • 访问器装饰器
    • 属性装饰器
    • 参数装饰器

基础语法

基础类型和对象类型

TypeScript中基础类型主要包括:number、string、null、undefined、boolean、symbol、void,对象类型包括了{}、[]、class、function等。

//基础类型:number、string、null、undefined、boolean、symbol、void
const count: number = 123;
const str: string = 'lx';//对象类型:
// 对象
const person: {name: string,age: number
} = {name: 'lx',age: 18
}
//数组
const numbers: number[] = [1, 2, 3];
// 类
class Person {}
const lx: Person = new Person();
//函数
const getTotal: () => number = () => {return 123;
}

定义的变量有可能有多种类型如何书写?

const a: number | string = 123;
const arr: (number | string)[] = [1, 'b', 2];

类型注解和类型推断

1、类型注解(type annotation):我们来告诉TS变量是什么类型
2、类型推断(type interface): TS会自动去尝试分析变量的类型
如果TS能自动分析变量类型,我们就不需要写类型注解;如果TS无法分析变量类型,我们就需要雪上类型注解

let countInterface = 1;
const first = 1;
const second = 2;
//如果定义变量写为两行,需要使用类型注解
let count: number;
count = 123;


鼠标移入到变量名上TS会自动分析出变量类型,此时我们就不用去写类型注解

//getTotal中参数需要类型注解,因为不知道调用该方法会传入什么类型的参数
function getTotal(first: number, second: number) {return first + second
}
//TotalCount为getTotal方法的返回值,现在确定为number类型,所以不用类型注解
const totalCount = getTotal(1, 2)

函数相关类型

1、确定函数返回类型

//函数返回类型为number
function add(x: number, y: number): number {return x + y
}
// 函数没有返回值
function sayHello(): void {console.log('hello');
}
// 函数不会执行到最后一行
function errorEmitter() : never {throw new Error()console.log(123)
}

2、函数形参解构赋值

// 即使只有一个参数也要用对象的方式
function add({fir, sec}: {fir: number, sec: number}): number {return fir + sec
}
const total = add({fir: 1, sec: 2});

3、多种定义函数的方式

function fun1(str: string): number {return parseInt(str, 10)
}
const fun2 = (str: string): number => {return parseInt(str, 10)
}
// 一般返回类型能够确定就不需要类型注解
const fun2 = (str: string) => {return parseInt(str, 10)
}
// 下面的类型注解不能省略,因为语法会错误
const fun3: (str: string) => number = (str) => {return parseInt(str, 10)
}

数组与元组

1、数组

const arr: (number | string)[] = [1, 'b', 2];
const strArr: string[] = ['1', 'b', '2'];
const nullArr: null[] = [null, undefined];//类型别名 type alias
type Person = {name: string;age: number;
}
class Student {name: string;age: number
}
// 可以直接new一个实例,只要内部类型一样就可
const objectArr: Person[] = [new Student(),{name: 'lx',age: 18}
]

2、元组(tuple):类型和长度都要对应

const studentArr: [string, string, number] = ['lx', 'male', 18];
const studentList: [string, string, number][] = [['lx', 'male', 18],['lx1', 'male', 19],['lx2', 'female', 20]
]

Interface接口

1、官方定义:接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。
实际上,就是把一些共有的属性和方法等提取出来。看下面例子:

const getPersonName = (person: {name: string}): string => {return person.name
}
const serPersonName = (person: {name: string}, name: string) => {person.name = name
}

getPersonName 和serPersonName 方法中参数person都用到了{name: string}这样的格式校验,所以,现在可以把共有的{name: string}提取出来定义一个接口。

interface Person {//readonly name: string; 表示name只读name: string;age?: number; // ?:表示age可有可无[propName: string]: any;//表示接口内可以有其他的属性,属性的名字是string类型,值可为任意类型say(): string;// 属性可以有一个名为say的方法,该方法返回值为string类型
}
const getPersonName = (person: Person): string => {return person.name
}
const setPersonName = (person: Person, name: string) => {person.name = name
}
const person = {name: 'lx',sex: 'male',say: () => {return 'say hello'}
}
getPersonName({name: 'lx',sex: 'male',say: () => {return ''}
})// 当Person接口中没有sex的定义时,这么写会报错,此时typescript会对其进行强校验
//接口内有[propName: string]: any也不会报错
getPersonName(person)// 当Person接口中没有sex的定义时,缓存一下变量再传进去不会报错
setPersonName(person, 'zr')

2、一个类如果想应用一个接口,可以使用implements

//User类中必须要有name值和say方法;这个类必须要存在接口内存在的方法和属性
class User implements Person {name = 'lx';say() {return 'hello'}
}

3、接口的继承:

//Teacher 接口继承了Person接口内的所有属性和方法
interface Teacher extends Person {teach() : string
}
const serPersonName = (person: Teacher, name: string) => {person.name = name
}
const person = {name: 'lx',sex: 'male',say: () => {return 'say hello'},teach: () => {return 'teach'} // 此时person内必须要有teach方法
}

4、定义函数类型声明

//interface可以定义一个函数类型
interface sayHi {(word: string): string//函数必须接收一个word的参数,为string类型,返回值类型也是string类型
}
const say: sayHi = (word: string) => {return word
}

类和类的继承

1、TypeScript 是面向对象的 JavaScript。类描述了创建的对象共同的属性和方法。

class Person {name = 'lx';getName() {return this.name}
}
const person = new Person();
console.log(person.getName())

2、类的继承和重写

class Person {name = 'lx';getName() {return this.name}
}
class Teacher extends Person {getTeacherName() {return 'teach'}// 重写Person类中的getName方法getName() {return 'msld' + super.getName() // super代表父类// super使用场景:子类把父类的方法重写了,但是我还想调用父类的该方法就用super}
}
const person = new Person();
const teacher = new Teacher()
console.log(teacher.getName()) //maldlx
console.log(teacher.getTeacherName()) // teach

类中的访问类型和构造器

1、访问类型有三种:public、private。protected
public:类中属性和方法默认是public类型,允许在类的内外被调用
private:只允许在类内被调用
protected:只允许在类内及继承的子类中调用

class Person {name: string;private age: number;protected say() {this.name;this.age;return 'hello';}
}
class Teacher extends Person {sayHi() {this.age; // 报错this.say()}
}
const person = new Person()
console.log(person.name)
console.log(person.age)// 报错
console.log(person.say())// 报错

2、构造器constructor
每一个类中都有一个constructor方法,在被实例化时会自动执行该方法。

class Person {//传统写法// name: string;// constructor(name:string) {//   this.name = name// }//简化写法constructor(public name: string){}
}
const person = new Person('lx')
console.log(person.name) //lx

如果父类有构造器,子类也要声明构造器,就必须要在子类构造器中调用父类构造器,使用super()代表调用父类的构造器。且还要按照父类构造器的要求把参数传过去。如果父类中没有写constructor,子类中的constructor方法也要调用空的super()

class Person {constructor(public name: string){}
}class Teacher extends Person {constructor(public age: number) {super('lx');}
}
const teacher = new Teacher(18)
console.log(teacher.name) //lx
console.log(teacher.age) //18

静态属性、setter和getter

1、静态属性(static):挂载在类上,不是挂载在类的实例上。静态方法内只能访问静态成员,因为静态的内容是随着类的加载而加载的,它是先进入内存的。如果静态方法调用成员变量时,类没有被实例化时则会报错,所以限制静态方法只能使用静态成员
使用static实现一个简单的单例模式:

//单例模式
class Demo {private static instance: Demo; // 存储new出来的Demoprivate constructor(public name: string){}//static 私有属性,挂载在类上,可直接通过类名调用static getInstance() {if(!this.instance) {this.instance = new Demo('lx');}return this.instance;}
}
const demo1 = Demo.getInstance();
const demo2 = Demo.getInstance(); // 此时demo1和demo2是一模一样的实例
console.log(demo1.name) // lx
console.log(demo2.name) // lx

2、setter和getter

class Person {//使用private保护私有属性,不让其在类的外部被调用,一般在其前面加下划线表示私有属性constructor(private _name: string) {}// 如果想获取私有属性,可以使用get//现在在外部调用name其实是调用了实际的name值+msld,起到保密作用get name() { return this._name + 'msld' // 对name做一些处理后暴露在外部使用}// 对设置的name值做了一次处理,也相当于保护了name值set name(name: string) {const realName = name.split(' ')[0]this._name = realName}
}const person = new Person('lx');
console.log(person.name) //lxmsld
person.name = 'lx msld'
console.log(person.name)//lxmsld

抽象类

1、抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
2、抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。
3、父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
4、抽象类表示的是一种继承关系,一个类只能继承一个抽象类

//抽象类 里面的属性和方法是它的子类中的一些共有的属性和方法
// 抽象类自己也可以定义自己的属性和方法
abstract class Area{getName() {return 'lx'}// 定义抽象方法,在子类继承父类时要在子类中写好该抽象方法abstract getArea(): number
}
class Circle extends Area{getArea() {return 1}
}
class Square extends Area{getArea() {return 2}
}
const circle = new Circle()
console.log(circle.getName())// lx
console.log(circle.getArea())// 1
const square = new Square()
console.log(square.getName())// lx
console.log(square.getArea())// 2

进阶语法

TypeScript中的配置文件

1、tsc --init初始化一个ts项目,会生成一个tsConfig.ts文件(编译配置文件)。如果tsc使用不了,要全局安装TypeScript。
2、使用tsc demo.ts可以编译该文件,这种方式的编译不会执行tsConfig.ts。直接使用tsc编译会编译全部ts文件且执行config文件,但若我只想编译部分ts文件,可以在配置文件中配置 includeexclude或者 files配置项

{"include": ["demo.ts"],"exclude": ["demo1.ts"],"files": ["demo2.ts"],"compilerOptions": {...}
}

3、compilerOptions中有很多配置项,例举几个:
removeComments: 编译时去除ts文件中的注释
strictNullChecks:不强制进行null校验
rootDir:允许编译的文件路径
outDir:编译后文件存放的路径
incremental:上次编译过的文件就不会再编译,只编译修改过和未编译过的文件
noUnusedLocals:对局部定义未使用的变量做警告

更多配置可参考TypeScript官网

联合类型和类型保护

联合类型(Union Types)可以通过(|)将变量设置多种类型,赋值时可以根据设置的类型来赋值
只能赋值指定的类型,如果赋值其它类型就会报错。
类型保护:我们可以通过 typeofinstanceofin字面量类型将代码分割成范围更小的代码块,在这一小块中,变量的类型是确定的。

interface Bird{fly: boolean;sing: () => {}
}
interface Dog{fly: boolean;bark: () => {}
}
// 联合类型  Bird | Dog 这种方式
function trainAnimal(animal: Bird | Dog) {if(animal.fly) {(animal as Bird).sing(); // 断言方式的类型保护} else {(animal as Dog).bark();}
}function trainAnimalSec(animal: Bird | Dog) {if('sing' in animal) {// in语法的类型保护animal.sing(); } else {animal.bark();}
}function add(first: string | number, second: string | number) {if(typeof first === 'string' || typeof second === 'string') { // typeof语法的类型保护return `${first}${second}`} else {return first + second}
}class NumberObj {count: number;constructor(){this.count = 1}
}
function addSec(first: object | NumberObj, second: object | NumberObj) {// instanceof语法的类型保护if(first instanceof NumberObj && second instanceof NumberObj) { return first.count + second.count}return 0
}

Enum枚举类型

枚举使用 enum关键字来定义
枚举成员会被赋值为从 0 开始递增的数字,可手动赋值,同时也会对枚举值到枚举名进行反向映射:

enum Status {OFFLINE,ONLINE = 4,DELETE
}console.log(Status.OFFLINE) // 0
console.log(Status.ONLINE) // 4
console.log(Status.DELETE) // 5
console.log(Status[0]) // OFFLINE

手动赋值的枚举项可以不是数字,此时需要使用类型断言来让 tsc 无视类型检查 (编译出的 js 仍然是可用的),只可在最后一项赋值。

enum Status {OFFLINE,ONLINE,DELETE = <any>'a'
}
console.log(Status.DELETE) // a

泛型

泛型(generic):泛指的类型,用<>包裹
例举某一场景:定义一个方法,传两个参数,此时我想让两个参数的类型必须得一样,但又不确定都是什么类型时可使用泛型

函数中的泛型

//*********函数中的泛型**********
// add方法内两个参数类型都为T,T是不确定的类型,方法调用时才会确定
function Add<T>(first: T, second: T) {return `${first}${second}`
}
Add<string>('1', '2');
// 泛型内也可以使用多个类型
function Add1<T, P>(first: T, second: P) {return `${first}${second}`
}
Add1<string, number>('1', 2);
// 方法返回类型也可以使用泛型
function Add2<T, P>(first: T, second: P): T {return first
}
Add2<number, string>(1, '2');
// Add2<number, string>(1, '2')可以去掉类型写为Add2(1, '2')
// 前者是显示确定类型,后者根据类型推断隐式确定类型

方法的参数类型还可以为一个泛型数组

// ABC[]  和  Array<ABC>等价
function map<ABC>(param: Array<ABC>) {return param
}
map<string>(['123', 'hello'])

类中的泛型

class DataManage<T>{constructor(private data: T[]){}getItem(index: number): T {return this.data[index];}
}
const data = new DataManage([1, 2, 3])
console.log(data.getItem(2)) // 3

上面例子中,我想在getItem方法中返回this.data[index].name,因为在构造函数中定义的data是一个泛型数组,现在并不能确定this.data[index]是否有name属性,所以我们可以定义一个接口,然后让T继承该接口。此时我们传的数组参数中的每一项必须要满足有name属性

interface Item{name: string;
}class DataManage<T extends Item>{constructor(private data: T[]){}getItem(index: number): string {return this.data[index].name;}
}
const data = new DataManage([
{name: 'luo'
},
{name: 'x'
}])
console.log(data.getItem(0)) // luo
console.log(data.getItem(1)) // x

现在如果我想T的类型只能是string或number类型,不允许是其他类型如何处理?
可使用extends字段

class DataManage<T extends string | number>{constructor(private data: T[]){}getItem(index: number): T{return this.data[index];}
}
const data = new DataManage<string>(['123'])
console.log(data.getItem(0)) // 123

泛型中keyof的用法

// 泛型中的keyof
interface Person {name: string,age: number,gender: string
}
class Info {constructor(private info: Person) {}getInfo<T extends keyof Person>(key: T): Person[T] {return this.info[key]}
}const info = new Info({name: 'luo',age: 18,gender: 'man'
})
const i = info.getInfo('gender')
console.log(i) //man

keyof Person是对Person这个接口的每一个值做遍历
第一次遍历:
T extends ‘name’ =====> type T = ‘name’
key: ‘name’
返回值类型:Person[‘name’] = string

高级语法

类的装饰器

简单的说,类的装饰器就是对类修饰的一个工具。
1、其本身是一个函数,通过@符号来使用
2、如果想使用装饰器,需要在tsconfig.josn配置文件中将experimentalDecorators设置为true
3、装饰器是对类做修饰,而不是对实例做修饰,所以装饰器是在类定义好之后就立即执行。
4、类装饰器接收的参数是构造函数,在装饰器内可以对构造函数进行修改。

function decorator(constructor: any) {//创建一个getName方法constructor.prototype.getName = () => {console.log('luo')}
}@decorator
class Test{}const test = new Test();
(test as any).getName() // luo

可以使用工厂模式来判断是否对这个类做修饰(该方法容易理解但是不太正规)

function decorator(flag: boolean) {if(flag) {return function(constructor: any) {constructor.prototype.getName = () => {console.log('luo')}}} else {return function(constructor: any) {}}
}@decorator(true) // 通过传参来判断是否需要修饰Test类
class Test{}const test = new Test();
(test as any).getName() // luo

通过泛型来写正规的装饰器:
对装饰器中的泛型做一些解释:
(...args: any[]) => any是一个函数,返回值类型是any,参数是一个数组,数组里面值的类型也是any
new (...args: any[]) => any说明该函数是一个构造函数,T extends new (...args: any[]) => any表示T是一个类或者说是包含了一个构造函数的东西

function decorator<T extends new (...args: any[]) => any>(constructor: T) {return class extends constructor{name = 'msld'; // 无论test实例如何去设置name值,name始终为msldgetName() {return this.name}}
}
@decorator
class Test{name: string;constructor(name: string) {this.name = name}
}
const test = new Test('luo');
console.log(test); // class_1 { name: 'msld' }
(test as any).getName() // 直接使用test.getName()会报错

在上面所有的例子中,当调用getName方法时我们都不是直接使用test.getName()去调用。而是用了(test as any).getName()这样的方式做了处理。因为在Test类中本身没有getName方法,装饰器中新加的方法在实例中是找不到的。那么我们如何处理能让test直接调用getName方法呢?看下面代码:

//同样使用工厂模式 定义一个函数去返回装饰器
function decorator() {return function <T extends new (...args: any[]) => any>(constructor: T) {return class extends constructor{name = 'msld';getName() {console.log(this.name)return this.name}}}
}// 执行decorator方法  得到一个装饰器 然后再把类当作参数传进去  最后赋值给Test
// 此时Test上就会有装饰器中新加的getName方法了
const Test = decorator()(class {name: string;constructor(name: string) {this.name = name}
})
const test = new Test('luo');
console.log(test); // class_1 { name: 'msld' }
test.getName() // msld'

方法装饰器

官方定义:方法装饰器声明在一个方法的声明之前(紧靠着方法声明)。 它会被应用到方法的属性描述符上,可以用来监视,修改或者替换方法定义。
简单来说,就是可以对方法做一些修饰。
方法装饰器也是一个函数,接收三个参数:
(1)target:当修饰普通方法时,target对应的是类的prototype;当修饰静态方法时,target对应的是类的构造函数
(2)propertyKey:方法的名字
(3)descriptor:方法的属性描述符

function getNameDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {console.log(target, propertyKey, descriptor)  // { getName: [Function (anonymous)] } getName {//   value: [Function (anonymous)],//   writable: true,//   enumerable: true,//   configurable: true// }descriptor.writable = falsedescriptor.value = function() {return 'decorator';}
}class Test{name: string;constructor(name: string) {this.name = name;}@getNameDecoratorgetName() {return this.name;}
}let test = new Test('luo');
// 配置了descriptor.writable = false  就不可对该方法进行修改
// test.getName = () => {//   return '12345'
// }
// Cannot assign to read only property 'getName' of object '#<Test>'console.log(test.getName()) // decorator    通过descriptor.value对方法进行了重写

访问器装饰器

访问器装饰器类似于方法装饰器,也为一个函数,且接收的参数和方法装饰器一样。
访问器装饰器声明在一个访问器(get或set)的声明之前。

function visitDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {console.log(target, propertyKey, descriptor)  // { getName: [Function (anonymous)], name: [Getter/Setter] } name {//   get: [Function: get],//   set: [Function: set],//   enumerable: true,//   configurable: true// }descriptor.writable = false
}class Test{_name: string;constructor(name: string) {this._name = name;}getName() {return this._name;}@visitDecoratorget name() {return this._name}set name(name: string) {this._name = name}
}let test = new Test('lx');
// 配置了descriptor.writable = false 不能修改name
test.name = 'lll'
//  Invalid property descriptor. Cannot both specify accessors and a value or writable attribute
console.log(test.name)

注意:TypeScript不允许同时装饰一个成员的getset访问器,因为在装饰器应用于一个属性描述符(descriptor)时,它联合了get和set访问器,而不是分开声明的。

属性装饰器

属性装饰器同样是一个函数,使用@符号放在定义的属性之前,与上面的装饰器相比,有以下几点区别:
(1)函数参数只有两个:targetpropertyKey,不接受descriptor
(2)如果想设置descriptor,需要在函数内部定义一个descriptor来实现

function nameDecorator(target: any, propertyKey: string): any {const descriptor: PropertyDescriptor = {writable: false}return descriptor
}
class Test{@nameDecoratorname = 'luo';
}
let test = new Test();
test.name = 'msld' //TypeError: Cannot assign to read only property 'name' of object '#<Test>'

(3)不能在函数内直接修改属性的值,因为修改的是原型上的属性值,而不是实例上的属性值

function nameDecorator(target: any, propertyKey: string): any {target[propertyKey] = 'msld' // 这里修改的并不是实例上的name,而是原型上的name
}
class Test{@nameDecoratorname = 'luo';
}
let test = new Test();
console.log(test.name) // luo   这里不会输出装饰器中设置的name值msld
console.log((test as any).__proto__.name) // msld

参数装饰器

参数装饰器同样是一个函数,使用@符号放在定义的方法参数之前。
参数装饰器接收三个参数:targetpropertyKey(不是参数名,而是方法名)、parameterIndex(第几个参数)。
注意:参数装饰器只能用来监视一个方法的参数是否被传入。

function paramDecorator(target: any, propertyKey: string, paramIndex: number){console.log(target, propertyKey, paramIndex) //{ getInfo: [Function (anonymous)] } getInfo 0
}
class Test{getInfo(@paramDecorator name: string, age: number) {console.log(name, age)}
}
let test = new Test();
test.getInfo('lx', 18) //lx 18

typescript语法相关推荐

  1. TypeScript语法错误:Argument of type ‘string‘ is not assignable to parameter of type ‘Element‘. 解决方法

    问题描述 DOM插入元素节点报错. TypeScript语法错误: TS2345: Argument of type 'string' is not assignable to parameter o ...

  2. TypeScript语法基础

    TypeScript语法基础 1 TypeScript 是什么 2 获取TypeScript 3 变量声明 4 数据类型 4.1 Boolean.Number.String.字面量 4.2 any与u ...

  3. Vue3.x中自定义时钟钩子函数(TypeScript语法)

      钩子函数的运用能使我们的代码更加简洁且易于维护,那么在Vue3.x中钩子函数的编写方式是怎样的呢?   下面,我以一个点击获取当前时间的例子来记录钩子函数的编写过程. 创建hooks目录   一般 ...

  4. typescript语法高亮插件_JavaScript开发者必备的10个Sublime Text插件

    Sublime Text几乎是任何开发者在其工具箱的必备应用程序.Sublime Text是一款跨平台的,高度可定制的,高级的文本编辑器,既适合全功能的IDE(出了名的资源匮乏),又可匹配命令行编辑器 ...

  5. 如何通过离线安装的方式让sublime text具有TypeScript语法高亮的功能

    我机器上安装的sublime text 2打开后缀为ts的TypeScript文件,默认以纯文本的格式打开,不具备语法高亮: 从这个Github仓库下载TypeScript的语法高亮插件: https ...

  6. typescript语法高亮插件_vscode常用插件

    插件介绍 HTML Snippets > 初级H5代码片段及提示 HTML CSS Support > 初级H5代码片段及提示 Debugger for Chrome > 让 vsc ...

  7. TypeScript—语法简介

    TypeScript官方指导文档:https://www.tslang.cn/docs/home.html 基本类型 变量声明 使用let和const两个关键字声明变量,具体形式如下: let use ...

  8. TypeScript 语法

    目录 前言 一.TypeScript 数据类型 1.七种原始数据类型 (1).布尔--boolean (2).数字--number (3).字符串--string (4).对象值缺失--null 和 ...

  9. TS(TypeScript)语法快速入门

    namespace Test{//命名空间interface ITsInterface{//接口interfaceFunction();}class TsFather{//类//构造函数constru ...

最新文章

  1. 【CVPR2020来啦】不容错过的29个教程Tutorial !(附Slides下载链接)
  2. c语言程序中的基本功能,c语言程序中的基本功能模块为什么?
  3. php记录用户搜索历史记录,PHPCookei记录用户历史浏览信息的代码
  4. table ADR6 引起的equipment download error
  5. mvc的视图中显示DataTable的方法
  6. [文档].Altera - Avalon接口规范
  7. 数据结构与算法——贪心算法
  8. 东北大学软件项目管理与过程改进_可视化看板——汽车研发项目管理成功的奥秘...
  9. C语言控制台应用程序绘制曲线,C语言控制台绘制曲线的实现代码
  10. 为什么招聘高级前端开发这么难?
  11. 创业需要的学习能力不是读书考试做题也不是所谓的思维格局
  12. 艰难的时候总会过去,只要你能坚持下来~
  13. 前端实现动画的6种方式详解
  14. java byte binary_java byte 与 binary 转换
  15. Jni开发(二)Linux运行java测试代码
  16. 机器视觉最火应用领域
  17. Visual Studio2010安装教程
  18. php 读取文件函数效率,php使用file函数、fseek函数读取大文件效率分析
  19. VB 注册ocx控件的方法
  20. 2G GSM基站的工作原理

热门文章

  1. 机器学习笔记(七)——初识逻辑回归、不同方法推导梯度公式
  2. 剩余定理(孙子定理)
  3. JavaScript中的自执行函数和闭包实现过程
  4. c语言 define和int,C语言中define与const的用法区别分析
  5. php_extension moodle,[转载]PHP  Moodle二次开发
  6. linux配额管理的三要素,linux的配额管理
  7. 荷兰国旗问题的解决:额外空间复杂度O(1),时间复杂度O(N)
  8. 读书笔记:数字逻辑基础与verilog设计之数字系统设计流程03----------二进制除法器电路设计
  9. 【iOS】—— 分类、扩展和关联对象
  10. 操作系统实验—存储管理