JavaScript & TypeScript 学习总结

JavaScript总结

1.什么是JavaScript?

​ 简单来说,JavaScript 是属于 HTML 和 Web 的编程语言。

2.如何使用JavaScript

​ 在 HTML 中,JavaScript 代码必须位于 <script></script> 标签之间。

例如:
<script>
document.getElementById("demo").innerHTML = "JavaScript";
</script>
3.语法
JavaScript 语法是一套规则,它定义了 JavaScript 的语言结构。
var x, y;	// 声明变量
x = 7; y = 8;	// 赋值
z = x + y;	// 对变量进行计算
4.JavaScript 标识符

​ 标识符是名称。

​ 在 JavaScript 中,标识符用于命名变量(以及关键词、函数和标签)。在大多数编程语言中,合法名称的规则大多相同。在 JavaScript 中,首字符必须是字母、下划线(-)或美元符号($)。连串的字符可以是字母、数字、下划线或美元符号。

**提示:**数值不可以作为首字符。这样,JavaScript 就能轻松区分标识符和数值。

5.注释

​ 并非所有 JavaScript 语句都被“执行”。双斜杠 ///* 与 */ 之间的代码被视为注释。注释会被忽略,不会被执行。

6.关键字

​ JavaScript 关键词用于标识被执行的动作。var 关键词告知浏览器创建新的变量 。

7.数据类型

​ JavaScript 变量可存放数值,比如 100,以及文本值,比如 “xm xmm”。在编程中,文本值被称为字符串。JavaScript 可处理多种数据类型,但是现在,我们只关注数值和字符串值。字符串被包围在双引号或单引号中。数值不用引号。如果把数值放在引号中,会被视作文本字符串。

​ JavaScript 变量能够保存多种数据类型:数值、字符串值、数组、对象等等:

var length = 7;                             // 数字
var lastName = "Gates";                      // 字符串
var cars = ["Porsche", "Volvo", "BMW"];         // 数组
var x = {firstName:"xm", lastName:"xmm"};    // 对象
8.循坏

​ while循环 —— 每次迭代之前都要检查条件。

​ dowhile循环 —— 每次迭代后都要检查条件。

​ for 循环—— 每次迭代之前都要检查条件,可以使用其他设置。

9.类型转换

JavaScript 变量能够被转换为新变量以及另一种数据类型:

  • 通过使用 JavaScript 函数
  • 通过 JavaScript 本身自动转换
10.JavaScript 函数

​ JavaScript 函数是通过 function 关键词定义的。

函数声明:
function functionName(parameters) {
   要执行的代码
}

​ 被声明的函数不会直接执行。它们被“保存供稍后使用”,将在稍后执行,当它们被调用时。

函数表达式

​ JavaScript 函数也可以使用表达式来定义。函数表达式可以在变量中存储:

var x = function (a, b) {return a * b};

​ 在变量中保存函数表达式之后,此变量可用作函数:

var x = function (a, b) {return a * b};
var z = x(4, 3);

​ 上面的函数实际上是一个匿名函数(没有名称的函数)。存放在变量中的函数不需要函数名。它们总是使用变量名调用。上面的函数使用分号结尾,因为它是可执行语句的一部分。

11.JavaScript 对象

JavaScript 变量是数据值的容器。

这段代码把一个单一值(porsche)赋给名为 car 的变量

var car = "porsche";

对象也是变量。但是对象包含很多值。

这段代码把多个值(porsche, 911, white)赋给名为 car 的变量

var car = {type:"porsche", model:"911", color:"white"};

值以名称:值对的方式来书写(名称和值由冒号分隔)。

JavaScript 对象是被命名值的容器。

对象属性

(JavaScript 对象中的)名称:值对被称为属性

var person = {firstName:"xm", lastName:"xmm", age:18, eyeColor:"blue"};
属性属性值
firstNamexm
lastNamexmm
age18
eyeColorblue
对象方法

对象也可以有方法

方法是在对象上执行的动作

方法以函数定义被存储在属性中。

属性属性值
firstNamexm
lastNamexmm
age18
eyeColorblue
fullNamefunction() {return this.firstName + " " + this.lastName;}

方法是作为属性来存储的函数。

实例
var person = {
  firstName: "xm",
  lastName : "xmm",
  id       : 678,
  fullName : function() {
    return this.firstName + " " + this.lastName;
  }
};
this 关键词

在函数定义中,this 引用该函数的“拥有者”。

在上面的例子中,this 指的是“拥有” fullName 函数的 person 对象。

换言之,this.firstName 的意思是 this 对象的 firstName 属性。

对象定义

定义(创建)一个 JavaScript 对象:

实例
var person = {firstName:"xm", lastName:"xmm", age:18, eyeColor:"blue"};
访问对象属性

可以通过两种方式访问属性:

objectName.propertyName

或者

objectName["propertyName"]

例如

person.lastName;

或者

person["lastName"];
访问对象方法

可以通过如下语法访问对象方法:

objectName.methodName()
实例
name = person.fullName();
注意不要把字符串、数值和布尔值声明为对象!
12.JavaScript 数组
JavaScript 数组用于在单一变量中存储多个值。

​ 使用数组文本是创建 JavaScript 数组最简单的方法。

语法:
var array-name = [item1, item2, ...];
使用 JavaScript 关键词 new

下面的例子也会创建数组,并为其赋值:

实例
var myArray = new Array("a", "b", "c");
访问数组元素

我们通过引用*索引号(下标号)*来引用某个数组元素。

这条语句访问 myArray中的首个元素的值:

var name = myArray[0];

这条语句修改myArray中的首个元素:

myArray[0] = "d";

通过 JavaScript,可通过引用数组名来访问完整数组:

实例
var myArray = ["a", "b", "c"];
document.getElementById("demo").innerHTML = myArray; 
数组是对象

数组是一种特殊类型的对象。在 JavaScript 中对数组使用 typeof 运算符会返回 “object”。

但是,JavaScript 数组最好以数组来描述。

数组使用数字来访问其“元素”。在本例中,person[0] 返回 Bill:

数组:
var person = ["xm", "xmm", 18];

对象使用名称来访问其“成员”。在本例中,person.firstName 返回 Bill:

对象:
var person = {firstName:"xm", lastName:"xmm", age:18};
数组元素可以是对象

JavaScript 变量可以是对象。数组是特殊类型的对象。

正因如此,可以在相同数组中存放不同类型的变量。

可以在数组保存对象。也可以在数组中保存函数。甚至可以在数组中保存数组:

myArray[0] = Date.now;
myArray[1] = myFunction;
myArray[2] = myCars;
数组属性和方法

JavaScript 数组的真实力量隐藏在数组的属性和方法中:

实例
var x = myArray.length;   // length 属性返回元素的数量
var y = myArray.sort();   // sort() 方法对数组进行排序
length 属性

length 属性返回数组的长度(数组元素的数目)。

length 属性始终大于最高数组索引(下标)。

遍历数组元素

遍历数组的最安全方法是使用 “for” 循环:

实例
var myArray, text, len, i;

myArray = ["a", "b", "c", "d"];
len = myArray.length;
text = "<ul>";
for (i = 0; i < len; i++) {
     text += "<li>" + myArray[i] + "</li>";
} 
添加数组元素

向数组添加新元素的最佳方法是使用 push() 方法:

实例
var myArray = ["a", "b", "c", "d"];
myArray.push("e");                // 向 myArray 添加一个新元素 (e)
数组和对象的区别

在 JavaScript 中,数组使用数字索引

在 JavaScript 中,对象使用命名索引

数组是特殊类型的对象,具有数字索引。

何时使用数组,何时使用对象?
  • JavaScript 不支持关联数组
  • 如果希望元素名为字符串(文本)则应该使用对象
  • 如果希望元素名为数字则应该使用数组

TypeScript 总结

1.什么是TypeScript?

​ TypeScript是微软开发的一个开源的编程语言,通过在JavaScript的基础上添加静态类型定义构建而成。TypeScript通过TypeScript编译器或Babel转译为JavaScript代码,可运行在任何浏览器,任何操作系统。

2.TypeScript配置

​ 安装好NodeJS后,以管理员身份运行终端,使用npm -g install ts-node typescript命令进行全局安装。

3.TypeScript变量声明

​ let和const是JavaScript里相对较新的变量声明方式。let在很多方面与var是相似的,const是对let的一个增强,它能阻止对一个变量再次赋值。因为TypeScript是JavaScript的超集,所以它本身就支持let和const。

let 声明
let hello = "Hello!";
块作用域

当用let声明一个变量,它使用的是词法作用域或块作用域。 不同于使用 var声明的变量那样可以在包含它们的函数外访问,块作用域变量在包含它们的块或for循环之外是不能访问的。在catch语句里声明的变量也具有同样的作用域规则。

拥有块级作用域的变量的另一个特点是,它们不能在被声明之前读或写。 虽然这些变量始终“存在”于它们的作用域里,但在直到声明它的代码之前的区域都属于 时间死区。 它只是用来说明我们不能在 let语句之前访问它们,但我们仍然可以在一个拥有块作用域变量被声明前获取它。 只是我们不能在变量声明前去调用那个函数。

const 声明

const声明是声明变量的另一种方式。

const numLivesForCat = 9;

const声明与let声明相似,但是就像它的名字所表达的,它被赋值后不能再改变。 换句话说,它拥有与 let相同的作用域规则,但是不能对它重新赋值。

4.解构
解构数组

数组的解构赋值是最简单的解构:

let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2

这创建了2个命名变量 firstsecond。 相当于使用了索引,但更为方便:

first = input[0];
second = input[1];

解构作用于已声明的变量会更好:

[first, second] = [second, first];

作用于函数参数:

function f([first, second]: [number, number]) {
    console.log(first);
    console.log(second);
}
f(input);
对象解构

也可以解构对象:

let o = {
    a: "foo",
    b: 12,
    c: "bar"
}
let {a, b} = o;

这通过 o.a and o.b 创建了 a 和 b 。 注意,如果不需要 c 可以忽略它。

就像数组解构,可以用没有声明的赋值:

({a, b} = {a: "baz", b: 101});

注意,需要用括号将它括起来,因为Javascript通常会将以 { 起始的语句解析为一个块。

5.函数

函数是JavaScript应用程序的基础。 它帮助实现抽象层,模拟类,信息隐藏和模块。 在TypeScript里,虽然已经支持类,命名空间和模块,但函数仍然是主要的定义行为的地方。 TypeScript为JavaScript函数添加了额外的功能,让用户可以更容易地使用。

和JavaScript一样,TypeScript函数可以创建有名字的函数和匿名函数。 可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数。

this和箭头函数

JavaScript里,this的值在函数被调用的时候才会指定。 这是个既强大又灵活的特点,但是这需要花点时间弄清楚函数调用的上下文是什么。 但这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候。

为了解决这个问题,可以在函数被返回时就绑好正确的this。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 为此需要使用ECMAScript 6箭头语法。 箭头函数能保存函数创建时的 this值,而不是调用时的值。把函数表达式变为使用lambda表达式( () => {} )。 这样就会在函数创建的时候就指定了‘this’值,而不是在函数调用的时候。

重载

JavaScript本身是个动态语言。 JavaScript里函数根据传入不同的参数而返回不同类型的数据是很常见的。在TypeScript利用为同一个函数提供多个函数类型定义来进行函数重载同样可实现这样的功能。 为了让编译器能够选择正确的重载函数,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。 如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。

6.类

传统的JavaScript的程序使用函数和基于原型的继承来创建可重用的组件,从ECMAScript 6开始,JavaScript程序员将能够使用基于类的面向对象的方式。使用TypeScript,允许开发者现在就使用这些特性,并且编译后的JavaScript可以在所有主流浏览器和平台上运行,而不需要等到下个JavaScript的版本。

继承

在TypeScript里,可以使用常用的面向对象模式。当然,基于类的程序设计中最基本的模式是允许使用继承来扩展现有的类。

公共,私有与受保护的修饰符:public、private、protected、默认为public。
private:

当成员被标记成private时,它就不能在声明它的类的外部访问。

TypeScript使用的是结构性类型系统。 当比较两种不同的类型时,并不在乎它们从何处而来,如果所有成员的类型都是兼容的,就认为它们的类型是兼容的。

然而,当比较带有private或protected成员的类型的时候,情况就不同了。 如果其中一个类型里包含一个 private成员,那么只有当另外一个类型中也存在这样一个private成员, 并且它们都是来自同一处声明时,才认为这两个类型是兼容的。 对于 protected成员也使用这个规则。

protected:

protected修饰符与private修饰符的行为很相似,但有一点不同,protected成员在派生类中仍然可以访问。

构造函数也可以被标记成protected。 这意味着这个类不能在包含它的类外被实例化,但是能被继承。

抽象类

抽象类做为其它派生类的基类使用。 它们一般不会直接被实例化。 不同于接口,抽象类可以包含成员的实现细节。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。

抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。 抽象方法的语法与接口方法相似。 两者都是定义方法签名但不包含方法体。 然而,抽象方法必须包含 abstract关键字并且可以包含访问修饰符。

7.接口
介绍

TypeScript的核心原则之一是对值所具有的shape进行类型检查。 它有时被称做“鸭式辨型法”或“结构性子类型化”。 在TypeScript里,接口的作用就是为这些类型命名和为你的代码或第三方代码定义契约。

可选属性

接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 可选属性在应用“option bags”模式时很常用,即给函数传入的参数对象中只有部分属性赋值了。

带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。

可选属性的好处之一是可以对可能存在的属性进行预定义,好处之二是可以捕获引用了不存在的属性时的错误。

只读属性

一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性:

最简单判断该用readonly还是const的方法是看要把它做为变量使用还是做为一个属性。 做为变量使用的话用const,若做为属性则使用readonly。

8.模块

从ECMAScript 2015开始,JavaScript引入了模块的概念。TypeScript也沿用这个概念。

模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非明确地使用export形式之一导出它们。 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,必须要导入它们,可以使用 import形式之一。

模块是自声明的;两个模块之间的关系是通过在文件级别上使用imports和exports建立的。

模块使用模块加载器去导入其它的模块。 在运行时,模块加载器的作用是在执行此模块代码前去查找并执行这个模块的所有依赖。

TypeScript与ECMAScript 2015一样,任何包含顶级import或者export的文件都被当成一个模块。

模块导出

任何模块导出声明(比如变量,函数,类,类型别名或接口)都能够通过添加export关键字来导出。如果经常会去扩展其它模块,并且只导出那个模块的部分内容。 重新导出功能并不会在当前模块导入那个模块或定义一个新的局部变量。或者一个模块可以包裹多个模块,并把他们导出的内容联合在一起通过语法:export * from “module”。

默认导出

每个模块都可以有一个default导出。 默认导出使用 default关键字标记;并且一个模块只能够有一个default导出。 需要使用一种特殊的导入形式来导入 default导出。

default导出十分便利。 比如,像JQuery这样的类库可能有一个默认导出 jQuery或 , 并 且 我 们 基 本 上 也 会 使 用 同 样 的 名 字 j Q u e r y 或 ,并且我们基本上也会使用同样的名字jQuery或 使jQuery导出JQuery。

生成模块代码

根据编译时指定的模块目标参数,编译器会生成相应的供Node.js (CommonJS),Require.js (AMD),isomorphic (UMD), SystemJS或ECMAScript 2015 native modules (ES6)模块加载系统使用的代码。 想要了解生成代码中define,require 和 register的意义,请参考相应模块加载器的文档。

外部模块

在Node.js里大部分工作是通过加载一个或多个模块实现的。 可以使用顶级的 export声明来为每个模块都定义一个.d.ts文件,但最好还是写在一个大的.d.ts文件里。 使用与构造一个外部命名空间相似的方法,但是使用 module关键字并且把名字用引号括起来,可以方便之后import。

9.泛型

软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。

在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

使用泛型变量

使用泛型创建像identity这样的泛型函数时,编译器要求在函数体必须正确的使用这个通用的类型。 换句话说,必须把这些参数当做是任意或所有类型。

可以这样理解loggingIdentity的类型:泛型函数loggingIdentity,接收类型参数T,和函数arg,它是个元素类型是T的数组,并返回元素类型是T的数组。 如果我们传入数字数组,将返回一个数字数组,因为此时T的的类型为number。 这可以把泛型变量T当做类型的一部分使用,而不是整个类型,增加了灵活性。

泛型接口

注意:如果编译 TS 项目并查找泛型,则不会找到任何泛型。由于在 Javascript 中不支持泛型,所以在编译器生成的构建中不会看到泛型。泛型纯粹是用于编译时的开发安全网,它将确保代码的类型安全抽象。

泛型类

泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

与接口一样,直接把泛型类型放在类后面,可以帮助确认类的所有属性都在使用相同的类型。

类有两部分:静态部分和实例部分。 泛型类指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型。

10.装饰器

装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上。 装饰器使用@expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

例如,有一个@sealed装饰器,可以这样定义sealed函数:

function sealed(target) {
    // do something with "target" ...
}
装饰器工厂

如果要定制一个修饰器如何应用到一个声明上,需要写一个装饰器工厂函数。 装饰器工厂就是一个简单的函数,它返回一个表达式,以供装饰器在运行时调用。

可以通过下面的方式来写一个装饰器工厂函数:

function color(value: string) { // 这是一个装饰器工厂
    return function (target) { //  这是装饰器
        // do something with "target" and "value"...
    }
}
装饰器求值

类中不同声明上的装饰器将按以下规定的顺序应用:

  1. 参数装饰器,其次是方法访问符,或属性装饰器应用到每个实例成员。
  2. 参数装饰器,其次是方法访问符,或属性装饰器应用到每个静态成员。
  3. 参数装饰器应用到构造函数。
  4. 类装饰器应用到类。
类装饰器

类装饰器在类声明之前被声明(紧靠着类声明)。 类装饰器应用于类构造函数,可以用来监视,修改或替换类定义。 类装饰器不能用在声明文件中( .d.ts),也不能用在任何外部上下文中(比如declare的类)。

类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。

如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。

注意 如果要返回一个新的构造函数,必须注意处理好原来的原型链。

方法装饰器

方法装饰器声明在一个方法的声明之前(紧靠着方法声明)。 它会被应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义。 方法装饰器不能用在声明文件( .d.ts),重载或者任何外部上下文(比如declare的类)中。

方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名字。
  3. 成员的属性描述符

注意  如果代码输出目标版本小于ES5,Property Descriptor将会是undefined。

如果方法装饰器返回一个值,它会被用作方法的属性描述符

注意  如果代码输出目标版本小于ES5返回值会被忽略。

访问器装饰器

访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义。 访问器装饰器不能用在声明文件中(.d.ts),或者任何外部上下文(比如 declare的类)里。

注意  TypeScript不允许同时装饰一个成员的get和set访问器。取而代之的是,一个成员的所有装饰的必须应用在文档顺序的第一个访问器上。这是因为,在装饰器应用于一个属性描述符时,它联合了get和set访问器,而不是分开声明的。

访问器装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名字。
  3. 成员的属性描述符

注意  如果代码输出目标版本小于ES5Property Descriptor将会是undefined

如果访问器装饰器返回一个值,它会被用作方法的属性描述符

注意  如果代码输出目标版本小于ES5返回值会被忽略。

属性装饰器

属性装饰器声明在一个属性声明之前(紧靠着属性声明)。 属性装饰器不能用在声明文件中(.d.ts),或者任何外部上下文里。

属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名字。

注意  属性描述符不会做为参数传入属性装饰器,这与TypeScript是如何初始化属性装饰器的有关。 因为目前没有办法在定义一个原型对象的成员时描述一个实例属性,并且没办法监视或修改一个属性的初始化方法。 因此,属性描述符只能用来监视类中是否声明了某个名字的属性。

如果属性装饰器返回一个值,它会被用作方法的属性描述符

注意  如果代码输出目标版本小于ES5,返回值会被忽略。

如果访问符装饰器返回一个值,它会被用作方法的属性描述符

参数装饰器

参数装饰器声明在一个参数声明之前(紧靠着参数声明)。 参数装饰器应用于类构造函数或方法声明。 参数装饰器不能用在声明文件(.d.ts),重载或其它外部上下文里。

参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:

  1. 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
  2. 成员的名字。
  3. 参数在函数参数列表中的索引。

注意  参数装饰器只能用来监视一个方法的参数是否被传入。

参数装饰器的返回值会被忽略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值