js 面向对象

面向对象

通过函数模拟对象的继承

// 定义一个基类函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

// 一般将方法写在原型中可以降低内存的占用率
Person.prototype.info = function () {
  console.log("姓名:" + this.name + "年龄:" + this.age);
};

// 定义一个学生类函数
function Student(name, age, stuNo) {
  Person.call(this, name, age); // 这里指定作用域的 this 是继承的关键
  this.stuNo = stuNo; // 自有属性
}

// 定义一个老师类函数
function Teachers(name, age, major) {
  Person.call(this, name, age);
  this.major = major; //自有属性
}

// 原型重新赋值,实现继承关系(但是实际上这种写法是存在隐患的,
Student.prototype = Person.prototype;
Teachers.prototype = Person.prototype;

/*这里只针对 Student 的原型做了更改*/
// 因为 Student 和 Person 用的都是同一个prototype,当子类Student 重写方法的时候,父类同时也会被改写)
Student.prototype.info = function () {
  console.log("学生信息方法的重写");
};

// 实例化
let p1 = new Student("张三", 16, "x1002");
let t1 = new Teachers("老张", 26, "数学");

/*结果可以发现, Teachers 的 info 方法也做了更改*/
console.log(p1.stuNo); // x1002
p1.info(); // 学生信息方法的重写
t1.info(); // 学生信息方法的重写
console.log(Student.info === Person.info); // true

针对上述问题的一些改进

 组合继承

// 定义一个基类函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.info = function () {
  console.log("姓名:" + this.name + "年龄:" + this.age);
};

// 定义一个学生类函数
function Student(name, age, stuNo) {
  Person.call(this, name, age); // 这里指定作用域的 this 是继承的关键
  this.stuNo = stuNo; // 自有属性
}

// 定义一个老师类函数
function Teachers(name, age, major) {
  Person.call(this, name, age);
  this.major = major; //自有属性
}

// 这可以算是一个过渡函数
let F = function () {};
F.prototype = Person.prototype;

// 通过这个 new 已经重新开辟了一段内存,这样就断开了原型链上面的联系,同时保留了 父类函数原型上的方法
Student.prototype = new F();
Teachers.prototype = new F();

// 这里让我们的 constructor 重新指向 Student、Teachers
Student.prototype.constructor = Student;
Teachers.prototype.constructor = Teachers;

/*这里只改写Student 上面的info*/
Student.prototype.info = function () {
  console.log("学生信息方法的重写");
};

let s1 = new Student("小明", 16, "x22201");
let t1 = new Teachers("老张", 28, "数学");

// 显然这是改写之后的结果
s1.info(); //学生信息方法的重写

// 这是原来的味道
t1.info(); //姓名:老张年龄:28

先来手写一段深拷贝代码

function deepCopy(obj) {
  let newObj = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      if (typeof obj[key] === "object" && obj[key] != null) {
        newObj[key] = deepCopy(obj[key]);
      } else {
        newObj[key] = obj[key];
      }
    }
  }
  return newObj;
}

也完全可以采用深拷贝的方式,完成继承

/*
 先说说 序列化出现的一些问题
  let obj = { age: 20, test: undefined, fn: function () {} };
  // 通过序列化实现深拷贝,但是会丢失 undefined 的值 还有 函数
  let obj2 = JSON.parse(JSON.stringify(obj));
  console.log(obj)
  console.log(obj2)
*/

F.prototype = Person.prototype;
Student.prototype = deepCopy(Person.prototype);
Teachers.prototype = deepCopy(Person.prototype);

Student.prototype.constructor = Student;
Teachers.prototype.constructor = Teachers;

class 语法

class Person {
  // 静态 属性不会被实例化继承(但是我们可以通过 Person.eyes 来使用)
  static eyes = 2;
  constructor(name) {
    this.name = name;
  }
  // 针对 class 语法糖, 方法会自动放置到 prototype 上
  info() {
    console.log("this person name is " + this.name);
  }
}

let p1 = new Person("小敏");
console.log(p1);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值