class 类
TypeScript支持集成了可选的类型批注支持的ECMAScript 6的类
Box 类 {width,height,name,constructor} new
class Box{
width:Number;
height:Number;
name:String;
constructor(name:String,width:number){
this.name=name;
this.width=width;
}
}
var redbox=new Box('red',100);
tsc
var Box = /** @class */ (function () {
function Box(name, width) {
this.name = name;
this.width = width;
}
return Box;
}());
var redbox = new Box('red', 100);
上面约等于
function Box(name, width) {
this.name = name;
this.width = width;
}
new 创建对象、定义对象的语法糖
如果用new 来创建对象 new 的作用,就是省那么几行代码。
参照-> JS 的 new 到底是干什么的?
不用new语法糖,定义士兵
function 士兵(ID){
var 临时对象 = {}
临时对象.__proto__ = 士兵.原型
临时对象.ID = ID
临时对象.生命值 = 42
return 临时对象
}
士兵.原型 = {
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}
// 保存为文件:士兵.js
创建100个士兵
var 士兵们 = []
for(var i=0; i<100; i++){
士兵们.push(士兵(i))
}
兵营.批量制造(士兵们)
使用new创建
new 的作用,就是省那么几行代码。(也就是所谓的语法糖)
只要你在士兵前面使用 new 关键字,那么可以少做四件事情:
不用创建临时对象,因为 new 会帮你做(你使用「this」就可以访问到临时对象);
不用绑定原型,因为 new 会帮你做(new 为了知道原型在哪,所以指定原型的名字为 prototype);
不用 return 临时对象,因为 new 会帮你做;
不要给原型想名字了,因为 new 指定名字为 prototype。
士兵对象定义
function 士兵(ID){
this.ID = ID
this.生命值 = 42
}
士兵.prototype = {
兵种:"美国大兵",
攻击力:5,
行走:function(){ /*走俩步的代码*/},
奔跑:function(){ /*狂奔的代码*/ },
死亡:function(){ /*Go die*/ },
攻击:function(){ /*糊他熊脸*/ },
防御:function(){ /*护脸*/ }
}
// 保存为文件:士兵.js
创建100个士兵,(加了一个 new 关键字):
var 士兵们 = []
for(var i=0; i<100; i++){
士兵们.push(new 士兵(i))
}
兵营.批量制造(士兵们)
Shape类 {area,constructor (name,width,height),shoutout()} constructor 构造函数 public与private 全局与局部变量
class Shape {
//Shape 类中有两个属性 area 和 color,一个构造器 (constructor()), 一个方法是 shoutout() 。
area: number;
private color: string;
constructor ( public name: string, width: number, height: number ) {
this.area = width * height;
this.color = "pink";
};
shoutout() {
//this.name undefined
return "I'm " + this.color + " " + this.name + " with an area of " + this.area + " cm squared.";
}
}
var square = new Shape("square", 30, 30);
//构造器中参数(name, width 和 height) 的作用域是局部变量,所以编译以上文件,在浏览器输出错误结果如下所示:
console.log( square.shoutout() );
console.log( 'Area of Shape: ' + square.area );
//undefined
console.log( 'Name of Shape: ' + square.name );
//console.log( 'Color of Shape: ' + square.color );
//TS2341: Property 'color' is private and only accessible within class 'Shape'.
//console.log( 'Width of Shape: ' + square.width );
//console.log( 'Height of Shape: ' + square.height );
tsc
TS2341: Property ‘color’ is private and only accessible within class ‘Shape’.
var Shape = /** @class */ (function () {
function Shape(name, width, height) {
this.name = name;
this.area = width * height;
this.color = "pink";
}
;
Shape.prototype.shoutout = function () {
//this.name undefined
return "I'm " + this.color + " " + this.name + " with an area of " + this.area + " cm squared.";
};
return Shape;
}());
var square = new Shape("square", 30, 30);
Shape
Shape.propotype
square =new Shape() 原型链
square vs square2
var square2 = new Shape("square2", 30, 30);
square==square2
square.propotype==square2.propotype
Shape vs square
Shape.prototype.isPrototypeOf(square)
true
Shape3D类 extends Shape {volume,constructor (name,width,height,length,shoutout(),superShout()} super(调用父类构造器,调用父类方法,方法重写)
class Shape3D extends Shape {
volume: number;
constructor ( public name: string, width: number, height: number, length: number ) {
super( name, width, height );
this.volume = length * this.area;
};
shoutout() {
return "I'm " + this.name + " with a volume of " + this.volume + " cm cube.";
}
superShout() {
return super.shoutout();
}
}
var cube = new Shape3D("cube", 30, 30, 30);
console.log( cube.shoutout() );
console.log( cube.superShout() );
tsc __extends
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var Shape3D = /** @class */ (function (_super) {
__extends(Shape3D, _super);
function Shape3D(name, width, height, length) {
var _this = _super.call(this, name, width, height) || this;
_this.name = name;
_this.volume = length * _this.area;
return _this;
}
;
Shape3D.prototype.shoutout = function () {
return "I'm " + this.name + " with a volume of " + this.volume + " cm cube.";
};
Shape3D.prototype.superShout = function () {
return _super.prototype.shoutout.call(this);
};
return Shape3D;
}(Shape));
var cube = new Shape3D("cube", 30, 30, 30);
console.log(cube.shoutout());
console.log(cube.superShout());
对象 方法void返回值
class Site {
name():void {
console.log("Runoob")
}
}
var obj = new Site();
obj.name();
tsc
var Site = /** @class */ (function () {
function Site() {
}
Site.prototype.name = function () {
console.log("Runoob");
};
return Site;
}());
var obj = new Site();
obj.name();
Car 类{engine,constructor(engine),disp():void}
class Car {
// 字段
engine:string;
// 构造函数
constructor(engine:string) {
this.engine = engine
}
// 方法
disp():void {
console.log("函数中显示发动机型号 : "+this.engine)
}
}
// 创建一个对象
var obj = new Car("XXSY1")
// 访问字段
console.log("读取发动机型号 : "+obj.engine)
// 访问方法
obj.disp()
tsc
var Car = /** @class */ (function () {
// 构造函数
function Car(engine) {
this.engine = engine;
}
// 方法
Car.prototype.disp = function () {
console.log("函数中显示发动机型号 : " + this.engine);
};
return Car;
}());
// 创建一个对象
var obj = new Car("XXSY1");
// 访问字段
console.log("读取发动机型号 : " + obj.engine);
// 访问方法
obj.disp();
类的继承 Circle extends Shape
TypeScript 支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。
/类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。
TypeScript 一次只能继承一个类,不支持继承多个类,但 TypeScript 支持多重继承(A 继承 B,B 继承 C)。
class Shape {
Area:number
constructor(a:number) {
this.Area = a
}
}
class Circle extends Shape {
disp():void {
console.log("圆的面积: "+this.Area)
}
}
var obj2 = new Circle(223);
obj2.disp()
tsc
new Circle(223);父类的构造函数
var Shape = /** @class */ (function () {
function Shape(a) {
this.Area = a;
}
return Shape;
}());
var Circle = /** @class */ (function (_super) {
__extends(Circle, _super);
function Circle() {
return _super !== null && _super.apply(this, arguments) || this;
}
Circle.prototype.disp = function () {
console.log("圆的面积: " + this.Area);
};
return Circle;
}(Shape));
var obj2 = new Circle(223);
obj2.disp();
继承类的方法重写
类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写。 其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法。
class PrinterClass {
doPrint():void {
console.log("父类的 doPrint() 方法。")
}
}
class StringPrinter extends PrinterClass {
doPrint():void {
super.doPrint() // 调用父类的函数
console.log("子类的 doPrint()方法。")
}
}
tsc
_super.prototype.doPrint.call(this); // 调用父类的函数
var PrinterClass = /** @class */ (function () {
function PrinterClass() {
}
PrinterClass.prototype.doPrint = function () {
console.log("父类的 doPrint() 方法。");
};
return PrinterClass;
}());
var StringPrinter = /** @class */ (function (_super) {
__extends(StringPrinter, _super);
function StringPrinter() {
return _super !== null && _super.apply(this, arguments) || this;
}
StringPrinter.prototype.doPrint = function () {
_super.prototype.doPrint.call(this); // 调用父类的函数
console.log("子类的 doPrint()方法。");
};
return StringPrinter;
}(PrinterClass));
static 关键字
class StaticMem {
static num:number;
age:number=10;
//this.age = 10;
static disp():void {
console.log("num 值为 "+ StaticMem.num)
}
}
StaticMem.num = 12 // 初始化静态变量
StaticMem.disp() // 调用静态方法
tsc
typescript需要先定义num,javascript,可以先定义函数disp() {StaticMem.num},后添加属性赋值
var StaticMem = /** @class */ (function () {
function StaticMem() {
this.age = 10;
}
//this.age = 10;
StaticMem.disp = function () {
console.log("num 值为 " + StaticMem.num);
};
return StaticMem;
}());
StaticMem.num = 12; // 初始化静态变量
StaticMem.disp(); // 调用静态方法
判断每个对象的实例 instanceof 运算符
class Person{ }
var obj3 = new Person()
var isPerson = obj3 instanceof Person;
console.log("obj 对象是 Person 类实例化来的吗? " + isPerson);
tsc
var Person = /** @class */ (function () {
function Person() {
}
return Person;
}());
var obj3 = new Person();
var isPerson = obj3 instanceof Person;
console.log("obj 对象是 Person 类实例化来的吗? " + isPerson);
访问控制修饰符 public(默认) protected private
public(默认) : 公有,可以在任何地方被访问。
protected : 受保护,可以被其自身以及其子类访问。
private : 私有,只能被其定义所在的类访问。
class Encapsulate {
str1:string = "hello"
private str2:string = "world"
}
var obj4 = new Encapsulate()
console.log(obj4.str1) // 可访问
//console.log(obj4.str2) // 编译错误, str2 是私有的
//TS2341: Property 'str2' is private and only accessible within class 'Encapsulate'.
tsc
TS2341: Property ‘str2’ is private and only accessible within class ‘Encapsulate’.
var Encapsulate = /** @class */ (function () {
function Encapsulate() {
this.str1 = "hello";
this.str2 = "world";
}
return Encapsulate;
}());
var obj4 = new Encapsulate();
console.log(obj4.str1); // 可访问
console.log(obj4.str2); // 编译错误, str2 是私有的
类和接口 implements
类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用。
interface ILoan {
interest:number
}
class AgriLoan implements ILoan {
interest:number
rebate:number
constructor(interest:number,rebate:number) {
this.interest = interest
this.rebate = rebate
}
}
var obj5 = new AgriLoan(10,1)
console.log("利润为 : "+obj5.interest+",抽成为 : "+obj5.rebate )
tsc
如果AgriLoan 不添加接口ILoan 的interest属性
TS2420: Class ‘AgriLoan’ incorrectly implements interface ‘ILoan’.Property ‘interest’ is missing in type ‘AgriLoan’ but required in type ‘ILoan’.
var AgriLoan = /** @class */ (function () {
function AgriLoan(interest, rebate) {
this.interest = interest;
this.rebate = rebate;
}
return AgriLoan;
}());
var obj5 = new AgriLoan(10, 1);
console.log("利润为 : " + obj5.interest + ",抽成为 : " + obj5.rebate);
{x:xx,y:yy} 对象
//以下对象包含了标量,函数,集合(数组或元组)。
var object_name = {
key1: "value1", // 标量
key2: "value",
key3: function() {
// 函数
},
key4:["content1", "content2"] //集合
}
tsc
//以下对象包含了标量,函数,集合(数组或元组)。
var object_name = {
key1: "value1", // 标量
key2: "value",
key3: function() {
// 函数
},
key4:["content1", "content2"] //集合
}
sites对象 TypeScript 类型模板
var sites = {
site1:"Runoob",
site2:"Google",
sayHello: function () { } // 类型模板
};
// 访问对象的值
console.log(sites.site1)
console.log(sites.site2)
//TypeScript 类型模板
//sites.sayHello = function(){ return "hello";} //TS2339: Property 'sayHello' does not exist on type '{ site1: string; site2: string; }'.
sites.sayHello = function () {
console.log("hello " + sites.site1);
};
sites.sayHello();
tsc
var sites = {
site1: "Runoob",
site2: "Google",
sayHello: function () { } // 类型模板
};
// 访问对象的值
console.log(sites.site1);
console.log(sites.site2);
//TypeScript 类型模板
//sites.sayHello = function(){ return "hello";} //TS2339: Property 'sayHello' does not exist on type '{ site1: string; site2: string; }'.
sites.sayHello = function () {
console.log("hello " + sites.site1);
};
sites.sayHello();
//TS2339: Property ‘sayHello’ does not exist on type ‘{ site1: string; site2: string; }’
对象也可以作为一个参数传递给函数,如下实例:
var invokesites = function(obj: { site1:string, site2 :string }) {
console.log("site1 :"+obj.site1)
console.log("site2 :"+obj.site2)
}
invokesites(sites)
tsc
var invokesites = function (obj) {
console.log("site1 :" + obj.site1);
console.log("site2 :" + obj.site2);
};
invokesites(sites);
鸭子类型(Duck Typing)
鸭子类型(英语:duck typing)是动态类型的一种风格,是多态(polymorphism)的一种形式。
interface IPoint {
x:number
y:number
}
function addPoints(p1:IPoint,p2:IPoint):IPoint {
var x = p1.x + p2.x
var y = p1.y + p2.y
return {x:x,y:y}
}
// 正确
var newPoint = addPoints({x:3,y:4},{x:5,y:1})
// 错误
//var newPoint2 = addPoints({x:1},{x:4,y:3})
tsc
function addPoints(p1, p2) {
var x = p1.x + p2.x;
var y = p1.y + p2.y;
return { x: x, y: y };
}
// 正确
var newPoint = addPoints({ x: 3, y: 4 }, { x: 5, y: 1 });
// 错误
//var newPoint2 = addPoints({x:1},{x:4,y:3})
TS2345: Argument of type ‘{ x: number; }’ is not assignable to parameter of type ‘IPoint’.Property ‘y’ is missing in type ‘{ x: number; }’ but required in type ‘IPoint’.