JavaScript设计模式
-
工厂模式
工厂模式,适合用于创建大量相似的对象,将创建对象的步骤定义在函数中,每次传递参数调用该函数,就会在函数内生成一个新的对象,并且把该新对象返回出来
-
构造函数模式
工厂模式虽然可以创建大量相似的对象,但是无法解决对象识别问题
//构造函数模式 构造对象的函数 function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { console.log(this); console.log(this.name); }; //return this; 不需要return 系统自动完成 } // 使用new关键字 // 1. 创建一个新对象 // 2. 将新对象的_proto_指向构造函数的prototype对象 // 2. 将构造函数的作用域赋值新对象 this指向这个新对象 // 3. 执行构造函数中的代码(将属性和方法赋给里this对象) // 4. 返回新对象 系统自动完成 var person1 = new Person("小米", 20, "Software Engineer"); var person2 = new Person("Greg", 23, "Teacher"); console.log("person.constructor == Person"); console.log(person1.constructor == Person);//true console.log("person instanceof Person"); console.log(person1 instanceof Person);//true console.log("person instanceof Object"); console.log(person1 instanceof Object);//true即无法像person1通过instanceof 判断是Person的实例,
-
原型模式
概述:
创建一个空执行体的函数,然后给该函数的原型对象添加共享属性和共享方法
function Fruits() { } Fruits.prototype = { constructor: Fruits,//覆盖之后要重新指回来 name: "香蕉", color: "黄色", sayColor() { console.log(this.color); }, sayAdress() { console.log("海南"); } } let banana = new Fruits("香蕉","黄色"); banana.sayAdress(); banana.sayColor();原型模型没有私有属性和私有方法,并不是好用,所以常常搭配构造函数模式一起用;私有属性和方法放在构造函数中,共有属性和函数放在原型中
let desc = Object.getOwnPropertyDescriptor(Fruits.prototype, "constructor"); console.log(desc);重构之前 constructor属性特征enumerable默认设置false
使用原型模式常常会重构原型对象,重构之前 constructor属性特征enumerable默认设置false
获取原型对象
console.log(Person.prototype); console.log(person1.__proto__); console.log(Object.getPrototypeOf(person1));//返回原型对象 console.log(Person.prototype == person1.__proto__);//true给原型对象添加属性/方法
Person.prototype.adress = "广州"; person1.__proto__.sayAdress = function () { console.log(this.adress); } person2.sayAdress();//广州删除原型对象的属性或者方法
//删除属性/方法 delete Person.prototype.adress; person2.sayAdress();//undefined属性和方法的查找机制
该实例对象-->__proto__指向原型对象-->Object的原型对象-->undefined
person1.hobby = "play the guitar"; person1.__proto__.hobby = "Roller-skating"; Object.prototype.hobby = "go fishing"; console.log(person1.hobby);//play the guitar delete person1.hobby; console.log(person1.hobby);//Roller-skating delete person1.__proto__.hobby; console.log(person1.hobby);//go fishing delete Object.prototype.hobby; console.log(person1.hobby);//undefined如果在person1实例对象中找不到该属性,将往原型链上找,直到找到,否则找到null返回undefined
判断属性是否在对象上
对象.hasOwnProperty("属性") //true/false
判断属性是否在对象或者对象的原型链上
"属性" in 对象 //true/false
-
组合构造函数模式和原型模式
私有属性和方法放在构造函数中,共有属性和函数放在原型中
//添加大量方法 function Fruits(name, color) { this.name = name; this.color = color; } console.log(Fruits.prototype); let fruitsProto = Fruits.prototype let desc = Object.getOwnPropertyDescriptor(Fruits.prototype, "constructor"); console.log(desc); Fruits.prototype = { constructor: Fruits, sayColor() { console.log("color"); }, sayAdress() { console.log("海南"); } } let banana = new Fruits("香蕉", "黄色"); banana.sayAdress(); banana.sayColor(); -
动态模式
在构造函数动态给原型对象添加公共属性或者公共方法
function Person(name, age) { this.name = name; this.age = age; if(typeof this.sayName != "function") { Person.prototype.sayName = function() { console.log(this.name); } } } let person1 = new Person("小米",19); person1.sayName();该模式不能重构原型对象,否则会丢失动态添加的属性或者方法
-
寄生构造函数模式
function Host() { let parasite = {}; parasite.name = "新冠肺炎"; parasite.copy = function() { console.log("复制繁殖"); } return parasite; } let covid_19 = new Host(); covid_19.copy(); console.log(covid_19);寄生构造函数模式的原型对象指向Object的原型对象
-
稳妥构造函数模式
稳妥对象:实例方法不引用this;不使用new操作符调用构造函数
function Person(name,age) { let obj = {}; obj.sayName = function() { console.log(name+"年龄"+age+"岁"); } return obj; } let person1 = Person("小米",20); person1.sayName();返回一个对象,该对象方法的执行上下文 为构造函数执行创建的作用域