JavaScript的面向对象

Posted 还是不会呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript的面向对象相关的知识,希望对你有一定的参考价值。

创建多个对象的方案

在上一篇文章JavaScript的面向对象(一),知道了创建对象的方式,那么可以参考一下,用来批量创建对象。

如:创建学生1,学生2,学生3,具有学号,姓名,学习属性。

这种方法是可以,但是存在大量的重复代码,存在一系列问题,要批量创建一些类相似的对象,这种方法显然是不是首选的。

创建对象方案:工厂模式

工厂模式是一种批量创建对象的设计模式

function createStu(sno, name) {
  var stu = {};
  stu.sno = sno;
  stu.name = name;
  stu.studying = function () {
    console.log(this.name + "正在学习~");
  };
  return stu;
}

var stu1 = createStu(201801, "stu1");
var stu2 = createStu(201802, "stu2");
var stu3 = createStu(201803, "stu3");
stu1.studying(); // stu1正在学习~
stu2.studying(); // stu2正在学习~
stu3.studying(); // stu3正在学习~

弊端:1、创建出来的对象是不知道具体的类型的,只知道是一个object类型

            2、对于用同一种工厂创建出来的对象内的方法,这些方法结构是相似的,没必要创建一个对象就给这个对象单独的一个函数,这样十分耗费内存。

所以说,工厂模式也不是批量创建对象的首选方法。

构造函数模式

什么是构造函数

通过new关键字调用一个函数,来实例化一个对象,这个函数就可以称之为构造函数。

构造函数创建对象的过程

1、创建一个新的对象.

2、将这个对象的[[prototype]]属性指向这个构造函数的prototype属性.

3、修改构造函数内部的this指向,使this指向新创建的对象.

4、执行构造函数内的代码.

5、把创建的新对象返回出去.

function Student(sno, name) {
  this.name = name;
  this.sno = sno;
  this.studying = function () {
    console.log(this.name + "正在学习~");
  };
}
var stu1 = new Student(201801, "stu1");
var stu2 = new Student(201802, "stu2");
var stu3 = new Student(201803, "stu3");
stu1.studying(); // stu1正在学习~

弊端:对于用同一构造函数创建出来的对象内的方法,这些方法结构是相似的,没必要创建一个对象就给这个对象分配单独的函数,这样十分耗费内存。

再次改进ing

构造函数+原型 模式

原型

每一个对象都有一个属性[[prorotype]],这个属性就是原型,也称之为:隐式原型.

对于属性 [[prorotype]]一般在代码中用__proto__来代替,__proto__在ECMA内没用明确的标准,这是由浏览器实现的,存在兼容性问题。但在ECMA标准内存在一个方法调用:Object.getPrototypeOf

这个属性指向另一个对象,这个对象又叫做 原型对象

对于一个函数,函数存在另一个属性 prorotype,这个属性在ECMA内是存在的,也指向另外一个对象(原型对象)。

由于之前说明了构造函数会将 新创建对象的属性 [[prototype]] 指向构造函数的 prototype.那么创建的对象的[[prototype]]指向构造函数对于的原型对象`.

对于一个对象,通过引用对象的属性key来获取一个value时,会触发[[Get]]操作:

1、先看对象本身上有没有对应属性,有的化使用本身对象上的属性。

2、如果本身对象上找不到,那么就到该对象的[[prototype]]内置属性指向的对象上的属性。

原型对象上的 constructor

实际上原型对象上存在一个属性 constructor ,这个属性指向的时 当前的函数对象。

构造函数+原型实现

那么可以将构造函数内共有的方法,放置到函数对应得原型对象上,对象在本身找不到对应方法时,由于构造函数创建对象的过程,就会到原型对象上查找,从而解决公共方法耗费内存得问题。

function Student(sno, name) {
  this.name = name;
  this.sno = sno;
}
Student.prototype.studying = function () {
  console.log(this.name + "正在学习~");
};
var stu = new Student(201801, "stu");
stu.studying(); // stu正在学习~
var stu1 = new Student(201802, "stu1");

console.log(stu.__proto__); // { studying: [Function (anonymous)] }
console.log(stu.__proto__ === Student.prototype); // true
console.log(stu.__proto__ === stu1.__proto__); // true

上述例子内存图

JS解析函数,实际上函数存储空间除了父级作用域[[scope]]函数执行体,其实还有一部分。

在堆内存内:

构造函数赋值新的原型对象

若需要放在原型对象上的属性,方法太多,为了方便编写,一般是直接赋值一个新的对象。

function Student(sno, name) {
  this.name = name;
  this.sno = sno;
}

Student.prototype = {
  studying: function () {
    console.log(this.name + "正在学习~");
  },
  eatting: function () {
    console.log(this.name + "正在吃饭~");
  },
  running: function () {
    console.log(this.name + "正在跑步~");
  },
};
// 默认平常打印原型对象时,也是看不见constructor的,
// 那么可以对 constructor 进行配置
Object.defineProperty(Student.prototype, "constructor", {
  configurable: true,
  enumerable: false,
  writable: true,
  value: Student,
});

内存表现:

以上是关于JavaScript的面向对象的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段12——JavaScript的Promise对象

VSCode自定义代码片段12——JavaScript的Promise对象

常用Javascript代码片段集锦

JavaScript单行代码,也就是代码片段

JavaScript对象原型链继承闭包

javascript 仿面向对象编程实例代码(私有,公共变量。。。)