JavaScript的面向对象
Posted 还是不会呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript的面向对象相关的知识,希望对你有一定的参考价值。
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对象