javascript-面向对象编程-[[prototype]]

前言

今天和大家探讨一下JavaScript-面向对象编程思想。本着学习交流心态,欢迎评论区抢座交流 ?

在讲JavaScript面向对象之前得引荐一下JavaScript的面向类设计模式的荒唐史.(es没有类的概念,es6 class关于类实现仅仅是语法糖而已)

基于类的语言 (如 Java 或 C++) 的开发人员来说,JavaScript 有点令人困惑,因为它是动态的,并且本身不提供一个 class 实现。(在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍然是基于原型的)。

es6class的引入确实降低了行为委托设计模式的工作量, 代码也更优美 .具体表现在,比如模仿类设计模式中,对于同名方法子类继承重写时,显示绑定this调用父类方法(多态).这是不好的习惯,会增加后期代码维护难度. 物不尽全美. class 同光也暴露出了一些弊端,比如super的调用问题.

es6的class 语法格式,同基于类的语言(java),类的写法类似. 但它并不是基于类的,不是面型类的设计模式.class实现的继承,仍然避免不了[[prototype]]机制的运用.这个是什么概念呢,后面一一解释.

总的来说,JavaScript是基于原型继承来实现面向对象的.

面向对象编程相关概念

面向对象对象编程

问题来了,说了这么多,究竟什么是面向对象编程?首先截一段官方解释,

面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。

其实也不难理解,其实就是对现实世界的实物,建立起抽象模型,深刻具体分析实物特征. 本质是一种抽象思维过程和面向对象的方法,然后组织代码实现实物具体,他是一种编程思想.

JavaScript面向对象编程几个核心概念:

  • 基础:对象.
  • 重要点:[[prototype]],继承,以及衍生出的行委托设计模式.

这里需要重点说明一下:JavaScript中,并没有类的概念,有通过某些方法实现同类的操作,本质上同真正的类语言创建的类,以及内部运行机制还是有天壤之别的.

关于[[prototype]]可以这么理解: 它是一切对象的内置属性,指向是对其他对象的引用, 当我们访问属性时,就会用到这个.它把各对象连接成层级关系. 以便在属性访问时,通过遍历这条链查找属性方法. 这个链是我们所说的原型链.

接下来我举个遍历原型链的简单例子:

var a =  {};
var b = {
    c:2
};

var a = Object.create(b);

console.log(a.__proto__)	//2

object.create是object方法,用来关联两个对象,以实现"继承".这个例子有不足之处,即a变量是不用声明的,因为object.create在关联某一对象的时候,会return 一个新对象.

es5类理论

前面已经解释过了,JavaScript中是没有类的概念的. 但是程序员怎么会懈怠呢,想尽各种办法来模仿类的设计模式. 如, new 关键字,对函数构造调用,模仿类.

那么他们是如何实现模仿类的呢?看如下图:
在这里插入图片描述
这里类与类之间,以及类与实列之间,从下之上表现出一种继承关系,这里通过原型.和类的从上至下关系,相差不大,但是继承原理不一样.传统类的继承实则是复制操作.

注:javascript中,所说的构造函数,和其他普通函数无任何区别. 如果说构造函数的名字首字母大写了.这里我想多说一句了,这个与名字大写不大写,没有直接联系.构造函数名字大写,只是编程的时候,大家约定俗称的约定,只要你愿意,你完全可以自行更改.

对于构造函数的解释是,凡是使用new调用的函数,都是构造函数调用,没有构造函数一说.

所以,可以通过构造函数形式来模仿类的实现,类函数.(参考上图)

原型风格:

function Foo() {
	this.name = name;
};

Foo.prototype.myName = function () {
	return this.name;
};
function Bar(name, label) {
	Foo.call(this, name);
	this.label = label;
}
//创建新bar.prototype关联到bar.prototype.
//注意此时默认的constructor也没有了,需要手动配置.
Bar.prototype = Object.create(Foo.prototype);

Bar.prototype.myLabel = function() {
	return this.label;
};

var a = new Bar ('a', 'obj a');	//this --> newobject  a
a.myName();
a.label();

上面的方法既是典型的基于原型风格.类构造模仿类,实现面向对象编程.

类构造函数面向类的过程,其实相比较与js字面量形式(真正的面向对象编程)面向对象过程任有些不足.
常谈及到的就是,显示绑定this的问题.加大了代码维护难度.

委托理论(字面量形式)

这里我们用一个例子来说明:
比如软件中,建模完成任务.首先我们会定义通用Task对象,里面包含任务通用的方法. 建模任务,xyz,abc.对象,各自需要完成不同任务. 创建对象存储对应的数据和行为. 对于任务数据的公共行为,我们关联到task,需要时调用方法即可.

Task = {
	setID(): funciton() { this.id = ID; },
	outputID: function() { console.log( this.id ); }
};
//xyz 委托到 Task
XYZ = Object.create( Task );

XYZ.preparTask = funciton (ID,label) {
	this.setID(ID);
	this.label = label;
};
XYZ.outputTaskDetails = function() {
	this.output();	//内部委托
	console.log( this.label );
};

对比类构造来实现这一流程.总结性说明两者优缺点.
代码量:类构造绝对是一个庞大代码量(相对字面量来说),而且关联关非常复杂. 类当中的伪多态问题,这是不好的表现(用于重写的处理手段),不利于代码维护.(怎么难维护,不太清楚).委托行为中,却恰好避免了这一问题.使用了具有描述性的命名.

委托行为 :

委托理论意味着某些对象在找不到属性或者方法时,就会把请求委托给另外一个对象. 编程中又称委托行为设计模式,和字类,父类,继承,多态等概念不同. 他们的关系应该时任意之间的委托行为,形成一种网状.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值