JS的基本语法已经够让人自闭了,面向对象则更为与众不同。因为JS 的设计之初是不想引入 类似 “继承” 这样的功能, 后来还是加上了 原型模式 。
准备工作
原型模式
定义:原型模式是一种创建型设计模式,Prototype模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建
概括一下 :
1、原型模式创建对象时使用
2、原型模式出于优化性能而设计 ,且只有满足new对象结构比较复杂时才能优化性能(即构造函数复杂,例如 java 中 clone()方法 ,对于空构造方法比new对象更为费时间 )
3、 发生在ram中, 有利有弊
工厂模式
比较常用的设计模式,在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
JavaScript 面向对象
1、对象构造器(constructor)
构造器穿件对象是改进自 工厂模式创建对象。
fuction Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
var person1 = new Person("Alex", 24, "pg");
注: 由于其“优秀”的设计,通用的方法this会bind到对象 , function写在外面 ,似乎不太合理?
2、原型模式创建对象
构造函数创建对象存在一个问题 : 构造函数中的每个方法都需要在实例对象中重新创建一遍,不能复用。所以使用原型模式创建对象似乎更合理。
理解:
原型指针 prototype 是Object 内置的一个指针(即 constructor),指向函数的原型对象。js 通过原型的方式 完成 对象的特殊继承。所有的对象最终指向Object。
原型链 : 由于数据类型不受 原型的束缚, 所有对象的类型拥有 属性 proto 属性, 用于向上查找。通过 proto向上查找 形成 “原型链”
fuction Person(){}
Person.prototype.name = "Alex";
Person.prototype.age = 24;
Person.prototype.job = "pg";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
即使不给初始属性值的,会用默认值!书上很长的篇幅讲解原理P150。
3、(建议)使用原型模式 + 构造函数模式:
原型模式还是存在弊端 , 这样下去,每new一个person对象,不仅默认值相同,如果要修改原型的话,另外对象的默认值也会发生影响。
简化原型模式的写法。
fuction Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
Person.prototype = {
constructor : Person,
sayName : function{
alert(this.name);
}
}
var person1 = new Person("Alex", 24, "pg");
ps : 后面还有多种创建对象方式
4、 继承
js可以使用至少5、6种继承方式。
https://www.cnblogs.com/ranyonsue/p/11201730.html
举例 :借用构造函数继承
fuction SuperType(name){
this.name = name;
}
function SubType(){
SuperType.call(this, "Alex");
this.age = 24;
}
call将父类函数引到子类函数中。继承的同时传递参数,继承的同时添加属性。组合继承 参考 P169 。
函数表达式、匿名函数、 闭包
1、
js 中函数是对象可以直接赋值给变量,无论有没有返回值。而变量只是表示一个地址。匿名函数被广泛使用,lambda表达式。
var sayHi = function(){
alert("hi");
};
// ==
var sayHi = s => {
alert(s);
};
sayHi("hi");
注意: 区别函数与函数表达式。
函数与函数表达式 作用域是不一样的,this 指向容易出现问题,重点注意使用 => 。 MDN 参考
2、递归
使用命名函数表达式 赋值给一个变量 :
var factorial = (
function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
}
);
3、闭包
你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数,因为ES6有了块级作用域的概念)。
函数内部再构建一个函数 , 将子函数return。
function outer() {
var a = '变量1'
var inner = function () {
console.info(a)
}
return inner // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}
(实话我是不怎么理解, 大概是作用域的问题 。 es6 之后用 let const 也很少出现问题)
4、模仿块作用区域
(同上 , es6 之后也不需再需要了)
(function(){
//块作用区域
})();
用于处理一些临时变量 时, 相当于 {}
, 第二个() 表示定义完 马上调用。
4、静态私有变量 P184
5、单例模式
简单单例模式
var Singleton = function(){
this.instance = null;
}
Singleton.getInstance = function () {
if(!this.instance){
this.instance = new Singleton();
}
return this.instance;
}
透明单例、懒惰单例 , 就不再赘述了。
网友评论