首页 > 其他分享 >07. 面向对象

07. 面向对象

时间:2023-01-25 19:22:27浏览次数:41  
标签:console log 对象 name 面向对象 原型 属性 07

一、什么是面向对象

  面向对象 (Object Oriented)是一种以 对象 为中心编程思想,简称 OO。面向对象将功能封装进对象,强调具备了功能的对象,以类/对象为最小单位,考虑谁来做。面向对象主要是把事物给对象化,对象包括属性与行为。

   (Class)和 对象 (Object)是面向对象的核心概念。类是对一类事物的描述,是抽象的、概念上的定义;对象是实际存在的该类事物的每个个体,因此也称为实例(instance);

二、面向对象的特征

2.1、封装

  对象就是一个用来存储不同属性的容器,对象不仅要存储属性,还要负责数据的安全。直接添加到对象的属性并不安全,因为它们可以被任意的修改。

  如何确保数据的安全:

  1. 私有化属性

    • 实例属性使用 # 开头就变成了私有属性;
    • 私有属性只能在类内部访问;
    • 私有属性一定要先声明在访问,否则报错;
  2. 提供 setter 和 getter 方法来开放对数据的操作

    • 使用 setter 和 getter 方法,可以控制属性的读写权限;
    • 使用 setter 和 getter 方法,可以在方法中对属性的值进行验证;
      get 属性名(){
         return this.#属性;
      }
    
      set 属性名(参数){
         this.#属性 = 参数;
      }
    
class Person{
    #name;
    #age;
    #gender;

    constructor(name,age,gender){
        this.#name = name;
        this.#age = age;
        this.#gender = gender;
    }

    sleep(){
        console.log(this.name + '睡觉了');
    }

    // getter方法,用来读取属性
    get name(){
        console.log('getter执行了');
        return this.#name;
    }

    // setter方法,用来设置属性
    set name(name){
        console.log('setter执行了');
        this.#name = name;
    }

    // getter方法,用来读取属性
    getAge(){
        return this.#age;
    }

    // setter方法,用来设置属性
    setAge(age){
        if(!isNaN(age)){
            if(age >= 0){
                this.#age = age;
            } 
        }   
    }

    getGender(){
        return this.#gender;
    }

    setGender(){
        this.#gender = gender;
    }
}

let p1 = new Person('Sakura',10,'女');

console.log(p1);

p1.setAge('abc');
console.log(p1.getAge());
p1.setAge(-11)
console.log(p1.getAge());
p1.setAge(12);
console.log(p1.getAge());

console.log(p1.name);
p1.name = 'Mikoto';
console.log(p1.name);

封装主要保证数据的安全,实现封装的方式:1.属性私有化;2.通过 getter 和 setter 方法来操作属性;

2.2、继承

  我们可以使用 extends 关键字来完成继承,当一个类继承另一个类是,就相当于将i另一个类中的代码复制到了当前类中(简单理解)。继承发生时,被继承的类称为 父类(超类),继承的类称为 子类。通过继承可以减少重复的代码,并且可以在不修改一个类的前提对其进行扩展。在子类中,可以通过创建同名方法来重写父类的方法。

class Animal{
    constructor(name){
        this.name = name;
    }

    sound(){
        console.log('动物在叫');
    }
}

class Dog extends Animal{
    // 重写构造函数
    constructor(name,age){
        // 重写构造函数时,构造函数的第一行代码必须为super()
        super(name);            // 调用父类的构造方法
        this.age = age;
    }
  
    // 子类重写父类的同名方法
    sound(){
        super.sound();          // 在方法中可以使用super来引用父类的方法
        console.log('汪汪汪');
    }
}


class Cat extends Animal{
    sound(){
        console.log('喵喵喵');
    }
}

let dog = new Dog('斯派克',3);
let cat = new Cat('汤姆');

console.log(dog);
dog.sound();
console.log(cat);
cat.sound();

重写构造函数时,构造函数的第一行代码必为为 super(),表示调用父类的构造函数;

在方法中可以使用 super 来引用父类的方法;

2.3、多态

  在 JS 中不会检查参数的类型,所以意味着任何数据都可以作为参数传递。要调用某个函数,无需指定的类型,只要对象满足某些条件即可。

class Person{
    constructor(name){
        this.name = name;
    }
}

class Dog{
    constructor(name){
        this.name = name;
    }
}

let dog = new Dog('大黄');
let person = new Person('张三');

console.log(dog);
console.log(person);

// 定义一个函数,这个函数将接收一个对象作为参数,它可以输出hello并打印对象的name属性
function hello(obj){
    console.log('hello,' + obj.name);
}

hello(dog);
hello(person);

三、对象的结构

  对象中存储属性的区域实际上有两个:

  • 对象自身
    • 比如直接通过对象所添加的属性,位于对象自身
    • 在类中通过 x = y 的形式添加的属性,位于对象自身中
  • 原型对象
    • 在对象中会有一个属性用来存储原型对象,这个属性叫做 __proto__
    • 原型对象也负责为对象存储属性
      • 当访问对象的属性时,会优先访问对象自身的属性,对象自身不包含该属性时,才会去原型对象中寻找
    • 会添加到原型对象的情况
      • 在类中通过 xxx(){} 方式添加的方法,位于原型中
      • 主动向原型中添加的属性和方法
class Person{
    name = 'Sakura';
    age = 10;

    constructor(){
        this.gender = '女';
    }

    hello(){
        console.log('My name is ' + this.name);
    }
}

let person = new Person();
person.addredd = '友枝町';
console.log(person);

四、原型对象

4.1、访问原型对象

  访问对象的原型对象:对象名.__proto__(不推荐)或者 Object.getProtoTypeOf(对象名)

class Person{
    name = 'Sakura';
    age = 10;

    hello(){
        console.log('My name is ' + this.name);
    }
}

let person = new Person();
console.log(person);
console.log(person.__proto__);
console.log(Object.getPrototypeOf(person));
console.log(person.__proto__ == Object.getPrototypeOf(person));

原型中的数据主要有两个部分:①、对象中的数据(属性、方法等);②、constructor(对象的构造函数);

原型对象也有原型,这样就构成一条原型链,根据对象的复杂程度不同,原型链的长度不同;即 person对象的原型链:person对象 --> 原型 --> 原型的原型 --> null;

读取对象属性时,会优先对象自身属性,如果对象中有,则使用,没有则去对象的原型中查找;如果原型中有,则使用,没有则去原型的原型中寻找,直到找到 Object 对象的原型,Object 对象的原型没有原型(为 null);如果依然没有找到,则返回 undefined;

4.2、原型的作用

  所有的同类型对象它们的原型对象都是同一个。原型就相当于是一个公共的区域,可以被所有该类的实例访问。我们可以将所有的公共属性(方法)统一存储到原型中,这样我们只需要创建一个属性,即可被所有实例访问。在对象中有些值是对象的独有的,像属性(name,age,gender)每个对象都应该有自己的值,但是有些值对于每个对象来说是一样的,像各种方法,对于一样的值没必要重复的创建。

class Person{
    name = 'Sakura';
    age = 10;

    hello(){
        console.log('My name is ' + this.name);
    }
}

let p1 = new Person();
let p2 = new Person();

console.log(p1 == p2);
console.log(Object.getPrototypeOf(p1) == Object.getPrototypeOf(p2));
console.log(p1.hello == p2.hello);
class Animal{

}

class Cat extends Animal{

}

// cat --> Animal实例 --> object --> Object原型 --> null
let cat = new Cat();
console.log(cat);
console.log(Object.getPrototypeOf(cat));
console.log(cat.__proto__.__proto__);
console.log(cat.__proto__.__proto__.__proto__);
console.log(cat.__proto__.__proto__.__proto__.__proto__);

在 JS 中。继承通过原型实现的,当我们继承是,子类的原型就是父类的实例。

4.3、修改原型

  可以通过类的 prototype 属性,来访问实例的原型。

class Person{
    name = 'Sakura';
    age = 10;

    hello(){
        console.log('My name is ' + this.name);
    }
}

let p1 = new Person();
let p2 = new Person();

// 通过类访问Person实例的原型对象
console.log(Person.prototype);

Person.prototype.sleep = () => {
    console.log('在睡觉');
}

p1.sleep();
p2.sleep();

千万不要通过类的实例去修改原型;

4.4、instanceof

  instanceof 检查一个类是否是一个类的实例。instanceof 检查的是对象的原型链上是否有该类的实例,只要原型链上有该类实例,就会返回 true。Object 是所有对象的原型,所以任何对象和 Object 进行 instanceof 运算都会返回 true。

class Animal{

}

class Dog extends Animal{

}

let dog = new Dog();
console.log(dog instanceof Dog);        // true
console.log(dog instanceof Animal);     // true

4.5、hasOwn

  • 使用 in 运算符检查属性时,无论属性在对象自身还是原型中,都会返回 true。
  • 对象.hashOwnProperty(属性名) 用来检查一个对象的自身是否含有某个属性(不推荐使用)。
  • Object.hasOwn(对象,属性名) 用来检查一个对象的自身是否含有某个属性(推荐使用)。
class Person{
    name = 'Sakura';
    age = 10;

    hello(){
        console.log('My name is ' + this.name);
    }
}

let person = new Person();

console.log('hello' in person);

console.log(person.hasOwnProperty('name'));
console.log(person.hasOwnProperty('hello'));

console.log(Object.hasOwn(person,'name'));
console.log(Object.hasOwn(person,'hello'));

标签:console,log,对象,name,面向对象,原型,属性,07
From: https://www.cnblogs.com/nanoha/p/17067161.html

相关文章

  • Day07-列表与元组
    一、定义列表1、列表可变数据类型2、[数据1,数据2,数据3,数据4,......]数据之间的逗号以英文分割,而且可以数据是不同类型的数据3、与字符串区别:字符串仅存储一个数据,列......
  • 面向对象-继承-2
    面向对象-继承-2......
  • 每日食词—day107
    middleadj. n. v.中间、中层、中段、中级的compactadj. n. v.压缩、紧密、紧凑abbreviatev.缩写、简写、缩短、简化、省略qualifiedadj. v.有资格的、......
  • 面向对象-继承-1
    面向对象-继承-1......
  • jn07本纪
    jn07,又名juun07,曾用名Takeshi,或者是kayTsa07,也有nana07,亦有艺名冬木军,然而更广为人知的名字是董哥。上图为董哥讲述自己id的来源。jn07于2007年6月24日......
  • 07_运算符
    """_*_coding:utf-8_*_@Time:2023/1/2218:53@Author:软柠柠吖@Description:运算符/:正常除(含小数)//:整除(返回商的整数部分,不四舍五入)......
  • 07-Model
    下面进入到了ORM的学习,ORM篇幅较长,因为函数太多。我们主要分为两个部分,Model和QuerySet元类在python中万物皆对象,类也是一个对象,自定义的类或是python中内置的类都......
  • CodeForces-907#B 题解
    正文设数组\(c_{x,y,i,j}\)代表\((x,y)\)位置的大格子中\((i,j)\)位置的小格子。很显然,输入中字符的输入顺序是要调整的,实际的顺序是\(x,i,y,j\)。对于输入的\(......
  • 面向对象程序设计 第五章 数据的共享与保护
    数据的共享与保护函数间的数据共享不同位置定义的变量和对象,其作用域、可见性、生存期都不同。程序模需要协作共同完成整个系统的功能,模块间需要共享数据,就需要知道应该......
  • Python面向对象(上)
    Python面向对象(上)python是一门面向对象的编程语言。何为对象?对象是类的实例。在生活中,任何一个事物都是一个对象,如牡丹花。牡丹花的类是花类,同样属于花类的还有荷花、月季......