阅读 133

TypeScript 面向对象中的属性和方法

属性和方法

接下来,我们学习面向对象中最基本的概念:属性和方法,在 TS 中是如何定义的?

class Cat {     // 属性     name;          // 方法     sayHi() {         return `Meow, my name is ${this.name}`;     } } let tom = new Cat(); tom.name = 'Tom'; console.log(tom.sayHi()); // Meow, my name is Tom 复制代码

修改下代码,我们就完成 TS 中对类的属性和方法的类型定义。

class Cat {     // 属性     name: string;          // 方法     sayHi(): string {         return `Meow, my name is ${this.name}`;     } } let tom = new Cat(); tom.name = 'Tom'; console.log(tom.sayHi()); // Meow, my name is Tom 复制代码

习题:关于类的属性和方法,下面用法正确的是?

// A class Animal {   age = 10;   getAge() {     return Animal.age;   } } new Animal().getAge(); // B class Animal {   age = 10;   getAge() {     return this.age;   } } new Animal().getAge(); // C class Animal {   age = 10;   getAge() {     return this.age;   } } new Animal().age; // D class Animal {   age = 10;   getAge() {     return this.age;   } } Animal.age; 复制代码

答案:BC

解析:

类的属性默认为实例属性,类的方法默认为实例方法。访问控制修饰符章节会详细介绍。

new Animal() 复制代码

使用 new 关键字对类 Animal 进行了实例化并返回实例化结果。

new Animal().getAge() 复制代码

链式写法,可以看作是 (new Animal()).getAge() 的省略写法。使用 new Animal() 得到类 Animal 的实例,接着实例执行 getAge 方法。

Animal.age 复制代码

当属性为静态属性(方法)时,可以直接使用类名调用该属性(方法)。

下图示意了静态属性和实例属性的区别,实例属性(方法)存在于实例对象中,每个实例对象都会单独拥有。静态属性(方法)存在于类中,所有实例对象共享静态属性(方法)。

静态方法和实例方法的区别

我们开始分析四个选项:

  • A - age 是类的实例属性,选项中 Animal.age 是静态方法的调用方式。故错误。

  • B - 选项中使用 this.age 是正确的。 this 指向实例对象。

  • C - 选项中 new Animal().age 调用是正确的。因为 age 是类的实例属性。

  • D - 基于 C选项可以看出,此选项是错误的。

资料:值为箭头函数的属性

假设我们要设计一个 Person 类,代码如下

class Person {     name: string     age: number     constructor(name: string, age: number) {         this.name = name;         this.age = age;     }     logName = function(name: string) {         console.log('my name is ' + name)     }     getName = function() {         this.logName(this.name)     } } const p1: Person = new Person('Richard', 12); const { getName } = p1; // 通过对象的解构赋值,提取出 getName  p1.getName(); // my name is Richard getName(); // TypeError: this.logName is not a function 复制代码

当我们将 getName 函数单独提取出来使用的时候,this 会指向 getName 运行时所在的作用域,这时候会因为找不到 logName 方法而报错。

一个可行的解决方案是用 bind 方法来为 getName 绑定作用域

class Person {     name: string     age: number     constructor(name: string, age: number) {         this.name = name;         this.age = age;     }     logName = function(name: string) {         console.log('my name is ' + name)     } // 利用 bind 方法为 logName 绑定作用域     getName = function() {         this.logName(this.name)     }.bind(this) } const p1: Person = new Person('Richard', 12); const { getName } = p1; // 通过对象的解构赋值,提取出 getName  p1.getName(); // my name is Richard getName(); // my name is Richard 复制代码

与 bind 方法相比,更简明的方法是利用 ES6 中提供的箭头函数。

class Person {     name: string     age: number     constructor(name: string, age: number) {         this.name = name;         this.age = age;     }     logName=function (name: string)  {         console.log('my name is ' + name)     } // 利用箭头函数为 logName 绑定作用域     getName = () =>{         this.logName(this.name)     } } const p1: Person = new Person('Richard', 12); const { getName } = p1 // 通过对象的解构赋值,提取出 getName  p1.getName(); // my name is Richard getName(); // my name is Richard 复制代码

资料:存取器

在 TypeScript 中,我们可以通过存取器来改变一个类中属性的读取和赋值行为

class User {     constructor(name: string) {         this.name = name;     }     get name() {         return 'Evan';     }     set name(value) {         console.log('setter: ' + value);     } } let a = new User('Peter'); // setter: Peter a.name = 'Richard'; // setter: Richard console.log(a.name); // Evan 复制代码

类的构造函数

在面向对象中,有一个特殊的方法,就是构造函数。构造函数就是在创建一个函数的时候,会被调用的函数。

接着上一个例子,我们希望创建这个 tom 的时候,就是初始化好它的姓名。

那如何去实现呢?

class Cat {     // 属性     // name: string;     // 这里可以定义好传入参数的类型     constructor(name: string) {         this.name = name;     }          // 方法     sayHi(): string {         return `Meow, my name is ${this.name}`;     } } let tom = new Cat('Tom'); // tom.name = 'Tom'; console.log(tom.sayHi()); // Meow, my name is Tom 复制代码

资料:参数属性

通常我们定义一个类的时候会采用如下写法

class User {     name: string;     age: number;     constructor() {         //...     } } 复制代码

实际上我们也可以在构造函数的参数定义时即声明和赋值属性

class User1 {     constructor(public name: string = 'Richard', private age: number = 18) {         //...     } } 复制代码

习题:关于类的构造函数,下面描述正确的是?

A. 主要用于初始化类的成员变量属性。

B. 类的对象创建时自动调用执行。

C. 没有返回值。

答案:A B C

解析:

类的构造函数主要用于,创建类的时候初始化类的成员变量属性。构造函数会在类的对象创建时候自动调用。需要注意的是父类的构造函数需要手动调用,因为构造函数主要用于初始化操作,故没有返回值。


作者:追梦玩家
链接:https://juejin.cn/post/7031024288270385189


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐