文章目录
写在前面
JavaScript与TypeScript:JavaScript是Web的编程语言,它控制了网页的行为,相比于TS,它在用户编程时,不会进行报错提醒,只有在代码运行的时候才会报错,是一款极度“自由”的语言,在自由的同时也带来了许多不便之处。而TypeScript的出现改变了这一点,它是JavaScript类型的超集,可以编译成纯JavaScript,它提供报错提醒,便于用户在编写代码时,及时修改代码。
一、Javascript
1.简介
JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。
HTML 中的 Javascript 脚本代码必须位于 < script > 与 < /script > 标签之间。Javascript 脚本代码可被放置在 HTML 页面的 < body > 和 < head > 部分中。
- 如图所示,这是我从该网页截取的部分代码
2.变量
变量是用于存储信息的"容器"
在JS中,用“var”来定义一个变量,例如:
var x=1;
var y=2;
var z=x+y;
与代数一样,JavaScript 变量可用于存放值(比如 x=1)和表达式(比如 z=x+y)。
变量可以使用短名称(比如 x 和 y),也可以使用描述性更好的名称(比如 age, sum, totalvolume)。
- 变量必须以字母开头
- 变量也能以 $ 和 _ 符号开头
- 变量名称对大小写敏感( U 和 u 是不同的变量)
数据类型
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
JavaScript 变量能保存以上的几种数据类型,其中最为常见的是字符串(“starboy”)
当向变量分配文本类型时,应该用双引号或单引号包围这个值,如:
var word=“starboy”;
当向变量赋的值是数值时,若用引号包围数值,该值会被作为文本来处理,如:
var a=“1”;
var b="2";
var c=a+b;
结果是:
c=12
3.操作符
操作符类型:一元操作符、布尔操作符、算术操作符、关系操作符、条件(问号)操作符、赋值操作符
- 一元操作符: ++ –
- 布尔操作符: && || !
除下列值为假外其余皆为真: false、null、undefined、''、0、NaN
- 算术操作符 + - * / %
- 关系操作符 <> <=>= == === != !==
其中“ ===”称为全等,即值和类型都要相等
- 条件(问号)操作符 ? :
能够有效简洁代码
- 赋值操作符 = += -+ *= /= %=
4.语句
JavaScript 语句由以下构成: 值、运算符、表达式、关键词和注释。
其中关键词有
关键词 | 含义 |
---|---|
break | 终止 switch 或循环 |
continue | 跳出循环并在顶端开始 |
debugger | 停止执行 JavaScript,并调用调试函数(如果可用) |
do … while | 执行语句块,并在条件为真时重复代码块 |
for | 标记需被执行的语句块,只要条件为真 |
function | 声明函数 |
if … else | 标记需被执行的语句块,根据某个条件 |
return | 退出函数 |
switch | 标记需被执行的语句块,根据不同的情况 |
try … catch | 对语句块实现错误处理 |
5.函数
函数( function)对任何语言来说都是一个核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、任何时候调用执行。
函数是包裹在花括号中的代码块,其前面使用了关键词 function
function [函数名]()
{
[执行代码]
}
若在执行代码中需要调用参数,则在函数定义之初需要传递参数
function [函数名](变量1,变量2,...,...,...)
{
[执行代码]
}
若执行完成代码后,需要返回一个希望的值,则需要return
function [函数名](变量1,变量2,...,...,...)
{
[执行代码]
return [变量];
}
大小写敏感
在JS中,函数名对大小写特别敏感,如
function hanshu(变量1,变量2,...,...,...)
{
[执行代码]
return [变量];
}
function hanShu(变量1,变量2,...,...,...)
{
[执行代码]
return [变量];
}
可以代表不同的两个函数,但是在命名函数名时,通常采用第二种命名方式,驼峰方法,即除第一个单词外,其余单词首字母大写,如:
function deleteString
、function showThisWord
等。
闭包
闭包是Closure,这是静态语言所不具有的一个新特性。简而言之,闭包就是:函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。
闭包就是就是函数的“堆栈”在函数返回后并不释放,可以理解为这些函数堆栈并不在栈上分配而是在堆上分配。
当我们在一个函数内定义另外一个函数就会产生闭包,它使得函数拥有私有变量变成可能,如:
function greeting(name) {
var text = 'Hello ' + name; // local variable
return function() { console.log(text); }//注意该函数无名称,称为匿名函数
}
var sayHello = greeting('Closure');
sayHello();
6.对象
对象 Object 是ECMAScript 中使用最多的一个类型。我们常将数据和方法封装在对象中,我个人觉得可以理解为C语言中的结构体
创建对象有两种方式
一是利用new构建一个空对象,然后再依次设置对象的属性,如:
var music = new Object();//生成空对象
music.name = 'Still young';//设置对象的属性
music.singer = 'Jason';
music.kind = 'passive';
music.player = function(){ //设置对象的方法
};
第二种方法是采用字面量的形式直接设置对象的属性,如:
var music = {
name: 'Still young',
singer: 'Jason',
kind: 'passive';
player: function(){
[执行代码]
}
};
一般来说,我们更常用第二种方法。
虽然 Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为解决这个问题,人们开始使用工厂模式的一种变体。代码如下:
function music(name, singer, kind){
var o = new Object();
o.name = name;
o.singer = singer;
o.kind = kind;
o.player = function(){
[执行代码]
};
return o;
}
var music1 = music('Still young', "Jason" , 'passive');
var music2 = music('become old', "Jason" , 'sadness');
var music3 = music('keep young', "Jason" , 'meaningful');
7.数组
数组用于在单一变量中存储多个值。
创建数组同样有两种方式:
- var [数组名] = [元素1, 元素2, …],如:
var supermarket_list=["fish","fruit","vagetable"]
- var [数组名] = new Array(元素1, 元素2, …);
var supermarket_list=new Array("fish",“fruit”,“vagetable”)
我们更常用第一种方法,因为第一种代码简洁、可读性强、执行速度更快。
8.链式语法
链式语法已变得非常流行。实际上这是一种非常容易实现的模式。
基本上,你只需要让每个函数返回,this代表包含该函数的对象,这样其他函数就可以立即被调用。如:
var bird = {
catapult: function() {
console.log( 'Yippeeeeee!' );
return this;
},
destroy: function() {
console.log( "That'll teach you... you dirty pig!" );
return this;
}
};
bird.catapult().destroy();
二、Typescript
1.变量
不同于JS(在JS中声明变量使用var),在TS中使用let或const申明变量,并加上类型说明,且作用域为块级即以{}为界
let表示变量,const类似常量
let (or const) [变量名]:[变量类型]
let item: string = 'TypeScript';
let item: number | string = 'TS';
item = 100;
let age: number = 89;
age = 64;
const pi: number = 3.14159;//pi以后不可改变,类似常量
解构
将对象、数组中的元素拆分到指定变量中,方便使用
- 解构数组
let input = [89, 64, 2018, 10];
let [first, second] = input;//
console.log(first); // 89
console.log(second); // 64
let [one, ...others] = input; //剩余变量
console.log(...others);
//展开
let newArr = [89, ...others, 18];
console.log(newArr);
- 解构成员
let o = {
a: "foo",
b: 12,
c: "bar"
};
let {a, b} = o;//注意使用{},且变量名需与对象中道属性名一致
console.log(a, b);
2.函数
函数是包裹在花括号中的代码块,其前面使用了关键词 function
- 无参函数:
function [函数名]:[类型]()
{
[执行代码]
}
- 带参函数:
function [函数名]:[类型]([参数1]:[类型],[参数2]:[类型],...)
{
[执行代码]
}
例如:
function add(x: number, y: number): number {
return x + y;
}
- 匿名函数
let [变量名] = function([类型]([参数1]:[类型],[参数2]:[类型],...):[函数类型] { [执行代码] };
例如:
let myAdd = function(x: number, y: number): number { return x + y; };
- 箭头函数
特点:简化函数定义、解决this问题
例如:
let greeting1 = () => `Hello TS!`;
let greeting2 = (name: string) => `Hello ${name}`;
console.log(greeting2('QiGe'));
let add1 = (n1: number, n2: number) => n1 + n2;
console.log(add1(1, 2));
let add2 = (n1: number, n2: number) => {
let sum = n1 + n2;
return sum;
3.类
类是属性和函数的集合,是生成对象或类实例的模板
类描述了所创建的对象共同的属性和方法。
TypeScript 支持面向对象的所有特性,比如 类、接口等。
- 类的定义和使用
class MyInfo { //class是关键字,类名默认全部大写首字母
name: string; //属性
weather: string; //属性
constructor(name: string, weather: string){ //构造函数,一般用于初始化。如果没有,TS会自动生成一个,以备用new创建类实例时调用。
this.name = name;
this.weather = weather;
}
printInfo(): void { //其它函数,无返回值
console.log(`Hello, ${this.name}.`);
console.log(`Today is ${this.weather}.`);
}
}
let myData = new MyInfo('QiGe', 'raining'); //使用new关键字生成对象,即该类的实例
myData.printInfo();
- 类的属性和函数的访问权限
- 类中的属性和函数都有访问权限,默认为public即全局可访问,其次为protected即可在类的内部和其子类的内部可访问,最后为private,只能在该类内部可访问。
class MyInfo { //class是关键字,类名默认全部大写首字母
public name: string; //public属性,可省略
private _weather: string; //私有属性,习惯以_开头进行命名
constructor(name: string, weather: string){ //构造函数,一般用于初始化
this.name = name;
this._weather = weather;
}
printInfo(): void { //其它函数
this._test();
console.log(`Hello, ${this.name}.`);
console.log(`Today is ${this._weather}.`);
}
private _test(): void {
console.log('You can not call me outside!');
}
}
let myData = new MyInfo('QiGe', 'raining'); //使用new关键字生成对象
console.log(myData._weather); //error!
myData._test(); //error
myData.printInfo();
- 存取器
- 若我们在类外部,要对类中的成员进行访问时,可以设置getter和setter操作其private属性,即使public属性也如此。
//getter和setter
class MyInfo { //class是关键字,类名默认全部大写首字母
private readonly _name: string; //私有属性,外部不可访问。readonly使其只能在初始化时赋值,以后不可更改。
private _weather: string; //私有属性,习惯以_开头进行命名
constructor(name: string, weather: string){ //构造函数,一般用于初始化
this._name = name;
this._weather = weather;
}
get name(): string {
return this._name;
}
set name(value: string) { //error! _name有readonly属性
this._name = value;
}
get weather(): string {
return this._weather;
}
set weather(value: string) {
this._weather = value;
}
}
let myData = new MyInfo('QiGe', 'raining'); //使用new关键字生成对象
console.log(myData.name, myData.weather);
myData.weather = 'sunny'; //OK
myData.name = 'Wang'; //error!
console.log(myData);
注意:readonly关键字将属性设置为只读的,只读属性必须在声明时或构造函数里被初始化。只带有get不带有set的存取器自动被推断为readonly。
- 静态属性
当类中的属性或函数被定义为静态时,即:static,则可直接使用,可以直接通过类名调用。
//静态属性,内建或自定义,无需new即可使用
console.log(Math.round(89.64)); //90
console.log(Math.pow(2, 8)); //256
class MyStaticClass {
static place = 'Earth';
static printInfo() {
console.log('We have only one Earth!');
}
}
console.log(MyStaticClass.place);
MyStaticClass.printInfo();
- 继承
关键字 extends,可以帮助类继承其他类,成为其子类,但是不能继承父类的私有成员(方法和属性)和构造函数。
class Animal {
// 当构造函数传入的参数加上了“访问权限控制符”,则同时会声明同名类属性,并赋值
constructor(public name: string) { }
protected log(message: string) {
console.log(message);
}
move(distanceInMeters: number = 0) {
this.log(`${this.name} moved ${distanceInMeters}m.`);//请注意name来自何处
this.log('==============');
}
}
class Horse extends Animal {
constructor(name: string) {
super(name); // 通过super调用父类构造器
}
run(distanceInMeters = 50) { //自己独有的函数
this.log("Clop, clop...");
super.move(distanceInMeters); // 通过super调用父类方法
}
}
class Eagle extends Animal {
constructor(name: string) { super(name); }
reborn() { //自己独有的函数
console.log('Reborn? It is a joke, hahaha!');
}
}
let tom: Horse = new Horse("Tommy the Palomino");
tom.run(8964);
let sam: Eagle = new Eagle("Sammy the Hawk");
sam.move(1024);//sam的move函数来自何处?
sam.reborn();
4.模块
对于大型的项目,我们需要使用模块进行管理。每个 .ts 文件就是一个模块,通过 export 来对外部模块暴露元素,通过 import
来引入模块。 模块是自声明的;两个模块之间的关系是通过在文件级别上使用imports和exports建立的。
采用以下语句建立模块:
export interface [模块名] {
// 代码部分
}
采用以下语句导入模块:
import { [模块名] } from " [模块所在路径] ";