引言javascript
因为一些特殊缘由因此,此次就讲解下基础的js插件封装。java
既然须要封装,那么就须要一个封装的容器,那这个容器是什么?函数
1.什么是对象性能
对象就是相似于 类的一个实例 好比同事是一个类,那我身边的一个同事就是一个对象。this
若是举个简单的例子:spa
var a =0;var b = “javascript”;var c = [1,2,3];var d = { key:11,value:22}
这些都是一个对象,可是光有对象还不行,还须要有构造。prototype
2.什么是构造函数插件
简单说构造函数是类函数,函数名与类名彻底相同,且无返回值。构造函数是类的一个特殊成员函数。指针
js建立构造的几种方式:code
1.工厂模式
考虑到在 ECMAScript 中没法建立类,开发人员就发明了一种函数,用函数来封装以特定接口建立对象的细节,以下面的例子所示:
function createPerson(id,name){ var o = new Object(); o.id = id; o.name = name; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson(1,27);
函数 createPerson()可以根据接受的参数来构建一个包含全部必要信息的 Person 对象。能够无数次地调用这个函数,而每次它都会返回一个包含三个属性一个方法的对象。工厂模式虽然解决了建立\多个类似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
主要好处就是能够消除对象间的耦合,经过使用工程方法而不是new关键字。将全部实例化的代码集中在一个位置防止代码重复。
工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,由于根本没法 搞清楚他们究竟是哪一个对象的实例。
2.构造函数模式
ECMAScript中的构造函数可用来建立特定类型的对象,像Array和Object这样的原生构造函数,在运行时会自动出如今执行环境中。此外,也能够建立自定义的构造函数,从而定义自定义对象的属性和方法。使用构造函数的方法,既解决了重复实例化的问题,又解决了对象识别的问题。例如,可使用构造函数模式将前面的例子重写以下:
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person('Grey',27,'Doctor');
Person()中的代码除了与 createPerson()中相同的部分外,还存在如下不一样之处:
没有显式地建立对象;
直接将属性和方法赋给了 this 对象;
没有 return 语句。
3.原型模式
咱们建立的每一个函数都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含能够由特定类型的全部实例共享的属性和方法。
若是按字面意思来理解,那么prototype就是经过调用构造函数而建立的那个对象实例的原型对象。使用原型对象的好处是可让全部对象实例共享它所包含的属性和方法。换句话说,没必要在构造函数中定义对象实例的信息,而是能够将这些信息直接添加到原型对象中。例如:
function Person(){ } Person.prototype.name = 'Nicholas'; Person.prototype.age = 29; Person.prototype.job = 'Software Engineer'; Person.prototype.sayName = function(){ alert(this.name); } var person1 = new Person(); person1.sayName();//"Nicholas" var person2 = new Person(); person2.sayName(); //"Nicholas" alert(person1.sayName == person2.sayName); //true
在此,咱们将 sayName()方法和全部属性直接添加到了 Person 的 prototype 属性中,构造函数变成了空函数。
即便如此,也仍然能够经过调用构造函数来建立新对象,并且新对象还会具备相同的属性和方法。但与构造函数模式不一样的是,新对象的这些属性和方法是由全部实例共享的。换句话说,person1 和 person2 访问的都是同一组属性和同一个 sayName()函数。要理解原型模式的工做原理,必须先理解 ECMAScript 中原型对象的性质。
3 继承
既然要实现继承,那么首先咱们得有一个父类,代码以下:
// 定义一个动物类 function Animal (name) { // 属性 this.name = name || 'Animal'; // 实例方法 this.sleep = function(){ console.log(this.name + '正在睡觉!'); } } // 原型方法 Animal.prototype.eat = function(food) { console.log(this.name + '正在吃:' + food); };
核心: 将父类的实例做为子类的原型
function Cat(){ } Cat.prototype = new Animal(); Cat.prototype.name = 'cat'; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.eat('fish')); console.log(cat.sleep()); console.log(cat instanceof Animal); //true console.log(cat instanceof Cat); //true
特色:
缺点:
new Animal()
这样的语句以后执行,不能放到构造器中核心:使用父类的构造函数来加强子类实例,等因而复制父类的实例属性给子类(没用到原型)
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特色:
缺点:
核心:为父类实例添加新特性,做为子类实例返回
function Cat(name){ var instance = new Animal(); instance.name = name || 'Tom'; return instance; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // false
特色:
new 子类()
仍是子类()
,返回的对象具备相同的效果缺点:
function Cat(name){ var animal = new Animal(); for(var p in animal){ Cat.prototype[p] = animal[p]; } Cat.prototype.name = name || 'Tom'; } // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // false console.log(cat instanceof Cat); // true
特色:
缺点:
核心:经过调用父类构造,继承父类的属性并保留传参的优势,而后经过将父类实例做为子类原型,实现函数复用
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); // true
特色:
缺点:
核心:经过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点
function Cat(name){ Animal.call(this); this.name = name || 'Tom'; } (function(){ // 建立一个没有实例方法的类 var Super = function(){}; Super.prototype = Animal.prototype; //将实例做为子类的原型 Cat.prototype = new Super(); })(); // Test Code var cat = new Cat(); console.log(cat.name); console.log(cat.sleep()); console.log(cat instanceof Animal); // true console.log(cat instanceof Cat); //true Cat.prototype.constructor = Cat; // 须要修复下构造函数
特色:
缺点: