我们都听说过面向对象,但实际在工作中可能写的不是很多,但不可否认它的重要性,当然,面向对象只是一种编程思维,并不是说我们一定要去使用它,理解面向对象,对你编程肯定是极有帮助的,那么让我们一起来看看js中的面向对象吧
一切皆为对象
大家都听说过这句话,但你真的能理解吗?
var a = '10'
如何证明上述代码也是对象?首先要理解我们在使用对象时候,通常是可以拿到对象的属性或者方法,那么我们是不是利用上面变量a.leng拿到长度,通过a.split()拿到并使用了split方法,至此,你觉得上面这个变量也可以看做一个对象有问题吗?
函数和方法、属性和变量
js中有很多概念是一个东西,但在不同环境下给予了不同名字,如题,那到底什么时候叫函数,什么时候叫方法?以及属性和变量
var arr = [1,2,3];
// 一个普通sum函数
function sum(){
console.log('函数')
}
// arr对象下的一个sum方法
arr.sum = function(){
console.log('方法')
}
var a = '10'; // 定义一个变量a=10,没有歧义
console.log(window.a); // 同样还是上面那个a,但在这个时候,a叫属性,属于window下的全局变量属性
综上,我们可以看出当一个变量或者函数在自由自在状态下它就是变量或者方法,当被某个对象去调用的时候它就是属性或者变量。
原始模式
下面代码先把它理解为“原始模式”
var obj = {};
obj.name = '小明';
obj.sex = '男';
obj.getName = function () {
console.log(this.name)
}
obj.getSex = function () {
console.log(this.sex)
}
obj.getName();
obj.getSex();
var obj2 = {};
obj2.name = '小花';
obj2.sex = '女';
obj2.getName = function () {
console.log(this.name)
}
obj2.getSex = function () {
console.log(this.sex)
}
obj2.getName();
obj2.getSex();
原始模式的改进:你肯定会想到将上面代码通过函数封装抽象,否则一旦实例数量多了,写起来就非常麻烦,那你可能会做下面的操作,通过写一个函数,解决代码重复的问题
function fn(name, sex) {
var name = name;
var sex = sex;
function getName() {
console.log(name);
};
function getSex() {
console.log(sex);
}
return {
getName,
getSex
}
}
var fn1 = fn('小明', '男');
fn1.getName();
fn1.getSex();
var fn2 = fn('小花', '女')
fn2.getName();
fn2.getSex();
工厂模式
了解面向对象,你不得不提的就是工厂模式,你可以简单理解工厂模式是面向对象的“雏形”,下面通过实例来分析工厂模式的优缺点
function fn(name, sex) {
// 原料
var obj = new Object();
// 加工
obj.name = name;
obj.sex = sex;
obj.getName = function () {
console.log('姓名:' + this.name)
};
obj.getSex = function () {
console.log('性别:' + this.sex)
};
// 出厂
return obj;
}
var fn1 = fn('小明', '男');
console.log(fn1.getName());
console.log(fn1.getSex());
var fn2 = fn('小花', '女');
console.log(fn2.getName());
console.log(fn2.getSex());
至此,那么上面代码还有哪些问题?1、逼格太低,代码浅显易懂。2、没有new。3、每个对象都有属于自己的方法函数。这个怎么理解呢?如下:
console.log(fn1.getName() == fn2.getName()); // 结果是false
虽然我们是做了封装,代码从表象来看是得到了较好的充分复用,但通过代码实际去对比会发现,其实我们每次调用都会开辟新的内存空间,资源浪费了。虽然如今终端设备已经性能很强悍,这点性能真的是九牛一毛(个人觉得真的意义不大),但既然是作为专业前端开发工程师,我们得秉承能省则省的原则让那些不明觉厉的沙屌闭嘴,下面来解决这个问题。
面向对象封装
function Fn(name, sex) {
this.name = name;
this.sex = sex;
}
Fn.prototype.getName = function () {
console.log(this.name);
};
Fn.prototype.getSex = function () {
console.log(this.sex);
};
var fn1 = new Fn('小明','男')
fn1.getName();
fn1.getSex();
var fn2 = new Fn('小花','女')
fn2.getName();
fn2.getSex();
console.log(fn1.getName() == fn2.getName()); // true
在面向对象方式编程中,通过new执行函数会改变this指向,属性每个对象各不相同,但方法是可以是同一个,所以prototype挂载的通常是方法,prototype可以理解为css中的class,给单独某个对象加属性方法相当于给行间样式