读书笔记-JavaScript设计模式-01面向对象的JavaScript

121 阅读4分钟

读书笔记-JavaScript设计模式-01面向对象的JavaScript

声明:本文更多的是对于笔者在上下班途中看书📖的书摘,基本上都是自己在微信读书上标注出来然后导出的,个别地方会加入些自己的理解,书名叫做《JavaScript的设计模式与开发实践》,感兴趣的可以自己购入哈,大佬可绕道。

1.面向对象的JavaScript

JavaScript没有提供传统面向对象语言中的类式继承,而是通过原型委托的方式来实现对象与对象之间的继承。

1.1 动态类型语言和鸭子类型:

  • 静态类型语言在编译时便已确定变量的类型,而动态类型语言的变量类型要到程序运行的时候,待变量被赋予某个值之后,才会具有某种类型。

  • 动态类型语言的缺点是无法保证变量的类型,从而在程序的运行期有可能发生跟类型相关的错误。

  • 鸭子类型:如果它走起路来像鸭子,叫起来也是鸭子,那么它就是鸭子。

1.2 多态:

多态的实际含义同一操作作用于不同的对象上面,可以产生不同的解释和不同的执行结果。换句话说,给不同的对象发送同一个消息的时候,这些对象会根据这个消息分别给出不同的反馈。

  • 多态的思想实际上是把“做什么”和“谁去做”分离开来,要实现这一点,归根结底先要消除类型之间的耦合关系。
  • 对象的多态性提示我们,“做什么”和“怎么去做”是可以分开的

1.3 封装:

  • 作用域创建: 除了ECMAScript 6中提供的let之外,一般我们通过函数来创建作用域
  • 描述的封装:指的是数据层面的封装。有时候我们喜欢把封装等同于封装数据
  • 封装的目的:是将信息隐藏,封装应该被视为“任何形式的封装”,也就是说,封装不仅仅是隐藏数据,还包括隐藏实现细节、设计细节以及隐藏对象的类型
  • **迭代器的作用:**是在不暴露一个聚合对象的内部表示的前提下,提供一种方式来顺序访问这个聚合对象
  • 封装类型是通过抽象类和接口来进行的
  • 封装:
    • 创建型模式:目的就是封装创建对象的变化。
    • 结构型模式:封装的是对象之间的组合关系。
    • 行为型模式:封装的是对象的行为变化。

1.4 原型模式和基于原型继承的JavaScript对象系统:

JavaScript本身是一门基于原型的面向对象语言,它的对象系统就是使用原型模式来搭建的,在这里称之为原型编程范型也许更合适

  • 原型模式不单是一种设计模式,也被称为一种编程泛型。

  • ECMAScript 5提供了Object.create方法,可以用来克隆对象

  • 依赖倒置原则提醒我们创建对象的时候要避免依赖具体类

  • 基于原型链的委托机制就是原型继承的本质

  • JavaScript中的根对象Object.prototype对象

JavaScript的函数既可以作为普通函数被调用,也可以作为构造器被调用

当使用new运算符来调用函数时,此时的函数就是一个构造器

new运算符来创建对象的过程,实际上也只是先克隆Object.prototype对象,再进行一些其他额外操作的过程。

  • __protp__JavaScript给对象提供了一个名为__proto__隐藏属性,某个对象的__proto__属性默认会指向它的构造器的原型对象,即{Constructor}.prototype

  • 对象的访问:如果对象无法响应某个请求,它会把这个请求委托给它的构造器的原型

  • **通过原型来完成能力借用:**当对象a需要借用对象b的能力时,可以有选择性地把对象a的构造器的原型指向对象b,从而达到继承的效果。

  • 设计模式是对语言不足的补充,如果要使用设计模式,不如去找一门更好的语言。

  • Object.create就是原型模式的天然实现

  • 除了根对象Object.prototype本身之外,任何对象都会有一个原型。而通过Object.create( null )可以创建出没有原型的对象。

	//在Chrome 和Firefox 等向外暴露了对象__proto__属性的浏览器下,我们可以通过下面这段代码来理解new 运算的过程:
	function Person( name ){
		this.name = name;
	};

	Person.prototype.getName = function(){
		return this.name;
	};

	var objectFactory = function(){
		var obj = new Object(), // 从Object.prototype 上克隆一个空的对象
		Constructor = [].shift.call( arguments ); // 取得外部传入的构造器,此例是Person
		obj.__proto__ = Constructor.prototype; // 指向正确的原型
		var ret = Constructor.apply( obj, arguments ); // 借用外部传入的构造器给obj 设置属性
		return typeof ret === 'object' ? ret : obj; // 确保构造器总是会返回一个对象
	};

	var a = objectFactory( Person, 'sven' );

	console.log( a.name ); // 输出:sven
	console.log( a.getName() ); // 输出:sven
	console.log( Object.getPrototypeOf( a ) === Person.prototype ); // 输出:true