标签:
function Person(name) { this.name = name; } Person.prototype.getName = function() { return this.name; }
下面是创建一个子类Author,用于继承Person:
分两步,第一步继承父类的属性,第二部继承父类的公共方法
function Author(name, books) { Person.call(this, name); // 通过这一行代码可以继承父类的属性 this.books = books; // 子类增添自己的属性 } Author.prototype = new Person(); // 继承父类方法的第一行代码 Author.prototype.constructor = Author; // 继承父类方法的第二行代码 Author.prototype.getBooks = function() { // 子类增添自己的方法 return this.books; };
这样就完成了一个简单的继承
二:编写一个extend函数来简化类的声明:
extend函数:
function extend(subClass, superClass) { var F = function() {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; }
function Author(name, books) { Person.call(this, name); this.books = books; } extend(Author, Person); Author.prototype.getBooks = function() { return this.books; };
function extend(subClass, superClass) { var F = function() {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype; if(superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; } }
function Author(name, books) { Author.superclass.constructor.call(this, name); this.books = books; } extend(Author, Person); Author.prototype.getBooks = function() { return this.books; }; Author.prototype.getName = function() { var name = Author.superclass.getName.call(this); return name + ‘, Author of ‘ + this.getBooks().join(‘, ‘); };
function clone(object) { function F() {} F.prototype = object; return new F; }
var Person = { name: ‘default name‘, getName: function() { return this.name; } };步骤二(通过原型式继承,创建Author原型):
var Author = clone(Person); Author.books = []; // Default value. Author.getBooks = function() { return this.books; }
var author = []; author[0] = clone(Author); author[0].name = ‘Dustin Diaz‘; author[0].books = [‘JavaScript Design Patterns‘]; author[1] = clone(Author); author[1].name = ‘Ross Harmes‘; author[1].books = [‘JavaScript Design Patterns‘]; author[1].getName(); author[1].getBooks();
var authorClone = clone(Author); alert(authorClone.name); // 调用的其实是Person.name // 所以输出的是字符串‘default name‘. authorClone.name = ‘new name‘; // 这样做其实就是在自己的对象中创建一个name属性 alert(authorClone.name); // 这样再使用name属性的时候,就会变成使用自己的name属性,而不是原型上的Person.name了 // 所以这时候的值是‘new name‘
authorClone.books.push(‘new book‘); // 对于数组也就是一样的道理,这行代码没有创建自身的books属性,等于直接操作原型里面的属性,所以就会导致原型的默认值编程‘new book’了,这会作用到其他使用原型继承的其他对象当中
authorClone.books = []; // 所以解决的方法就是在自身的对象中新建一个books数组 authorClone.books.push(‘new book‘); // 然后再进行对数组的操作
提示,通过hasOwnProperty可以去分对象的实际成员和它继承而来的成员
此外,上述的这种情况对于拥有对象属性的原型来说也是一样,其实我们也可以用同一种办法来解决,例如下面这个实例:
var CompoundObject = { string1: ‘default value‘, childObject: { bool: true, num: 10 } } var compoundObjectClone = clone(CompoundObject); // 这样做的话就会破坏原型的默认值了 compoundObjectClone.childObject.num = 5; // 这个解决方法和上面数组那个一样,在自身的原型里面创建一个心的childObject对象 compoundObjectClone.childObject = { bool: true, num: 5 };
var CompoundObject = {}; CompoundObject.string1 = ‘default value‘, CompoundObject.createChildObject = function() {//这个函数是关键,返回一份副本 return { bool: true, num: 10 } }; CompoundObject.childObject = CompoundObject.createChildObject();//这里就在原型里面先获取一次这个对象副本,原型就有了childObject属性 var compoundObjectClone = clone(CompoundObject); compoundObjectClone.childObject = CompoundObject.createChildObject();//这里就创建新对象自己的childObject属性 compoundObjectClone.childObject.num = 5;
如果要继承的话,最好父类使用门户大开方法
六: 掺元类:javascript中只能继承一个父类,所以如有一些不需要严格继承,但是很多类都用到的方法,我们就通过扩充的方式让这些类共享这些方法,例子:一个类(其实就是包含一个简单的toJSONString方法):
var Mixin = function() {}; Mixin.prototype = { serialize: function() { var output = []; for(key in this) { output.push(key + ‘: ‘ + this[key]); } return output.join(‘, ‘); } };
augment(Author, Mixin);让后就可以使用了:
var author = new Author(‘Ross Harmes‘, [‘JavaScript Design Patterns‘]); var serializedString = author.serialize();
function augment(receivingClass, givingClass) { for(methodName in givingClass.prototype) { if(!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } }
function augment(receivingClass, givingClass) { if(arguments[2]) { // Only give certain methods. for(var i = 2, len = arguments.length; i < len; i++) { receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; } } else { // Give all methods. for(methodName in givingClass.prototype) { if(!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } }
下面就是使用一个例子,来演示上所说的三种方法。
例子说明:假设你的任务就是编写一个用于创建和管理就地编辑域的可重用的模块化API(就地编辑是指网页上的一段普通文本被点击后就变成一个配有一些按钮的表单域,以便用户对这段文本进行编辑)。使用这个API,用户应该能够为对象分配一个唯一的ID值,能够为它提供一个默认值,并且能够指定其在页面上的目标位置。用户还应该在任何时候都可以访问到这个域的当前值,并且可以选择具体使用的编辑域(比如多行文本框或单行文本框)。
也就是说,平时是这个样子的:
点击之后会变成这样在的:
文本框中填写"改变文本",save后:
接下来,我们的需求更改了,要把input框变成textarea框,怎么办了?也就是说
点击之后要变成这样子:
方法一:类式继承解决方案
首先创建一个父类EditInPlaceField以及演示它的使用:
<html> <head> <meta http-equiv="charset" content="utf-8"></head> <body> <script> //类的定义 function EditInPlaceField(id, parent, value) { this.id = id; this.parentElement = parent; this.value = value || ‘default value‘; this.createElements(this.id); this.attachEvents(); } EditInPlaceField.prototype = { createElements: function (id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘span‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘input‘); this.fieldElement.type = ‘text‘; this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }, attachEvents: function () { var that = this; this.staticElement.addEventListener(‘click‘, function () { that.convertToEditable(); },false); this.saveButton.addEventListener(‘click‘, function () { that.save(); },false); this.cancelButton.addEventListener(‘click‘, function () { that.cancel(); },false); }, convertToEditable: function () { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘inline‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }, save: function () { this.value = this.getValue(); this.convertToText(); }, cancel: function () { this.convertToText(); }, convertToText: function () { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘inline‘; this.setValue(this.value); }, setValue: function (value) { this.fieldElement.value = value; this.staticElement.innerHTML = value; }, getValue: function () { return this.fieldElement.value; } } //类的使用 var body = document.body; var titleClassical = new EditInPlaceField(‘titleClassical‘, body, ‘Title Here‘); </script></body> </html>
function extend(subClass, superClass) { var F = function () {}; F.prototype = superClass.prototype; subClass.prototype = new F(); subClass.prototype.constructor = subClass; subClass.superclass = superClass.prototype; if (superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; } } //继承 function EditInPlaceArea(id, parent, value) { EditInPlaceArea.superclass.constructor.call(this, id, parent, value); }; extend(EditInPlaceArea, EditInPlaceField); EditInPlaceArea.prototype.createElements = function (id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘p‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘textarea‘); this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }; EditInPlaceArea.prototype.convertToEditable = function () { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘block‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }; EditInPlaceArea.prototype.convertToText = function () { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘block‘; this.setValue(this.value); }; var AreaObject = new EditInPlaceArea(‘AreaObject‘, body, ‘多行文本框默认值‘);
方法二:原型式继承解决方案
第一步:
<html> <head> <meta http-equiv="charset" content="utf-8"></head> <body> <script> function clone(object) { function F() {} F.prototype = object; return new F; } var EditInPlaceField = { configure: function (id, parent, value) { this.id = id; this.value = value || ‘default value‘; this.parentElement = parent; this.createElements(this.id); this.attachEvents(); }, createElements: function (id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘span‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘input‘); this.fieldElement.type = ‘text‘; this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }, attachEvents: function () { var that = this; this.staticElement.addEventListener(‘click‘, function () { that.convertToEditable(); }, false); this.saveButton.addEventListener(‘click‘, function () { that.save(); }, false); this.cancelButton.addEventListener(‘click‘, function () { that.cancel(); }, false); }, convertToEditable: function () { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘inline‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }, save: function () { this.value = this.getValue(); this.convertToText(); }, cancel: function () { this.convertToText(); }, convertToText: function () { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘inline‘; this.setValue(this.value); }, setValue: function (value) { this.fieldElement.value = value; this.staticElement.innerHTML = value; }, getValue: function () { return this.fieldElement.value; } }; var body = document.body; var titlePrototypal = clone(EditInPlaceField); titlePrototypal.configure(‘titlePrototypal ‘, body, ‘Title Here‘); </script></body> </html>
var EditInPlaceArea = clone(EditInPlaceField); EditInPlaceArea.createElements = function (id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘p‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘textarea‘); this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }; EditInPlaceArea.convertToEditable = function () { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘block‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }; EditInPlaceArea.convertToText = function () { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘block‘; this.setValue(this.value); }; //使用 var editInPlaceArea = clone(EditInPlaceArea); editInPlaceArea.configure(‘editInPlaceArea ‘, body, ‘editInPlaceArea‘);
方法三:掺元类解决方案
先把扩展类复制进代码中:
function augment(receivingClass, givingClass) { if (arguments[2]) { // Only give certain methods. for (var i = 2, len = arguments.length; i < len; i++) { receivingClass.prototype[arguments[i]] = givingClass.prototype[arguments[i]]; } } else { // Give all methods. for (methodName in givingClass.prototype) { if (!receivingClass.prototype[methodName]) { receivingClass.prototype[methodName] = givingClass.prototype[methodName]; } } } }
var EditInPlaceMixin = function() {}; EditInPlaceMixin.prototype = { createElements: function(id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘span‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘input‘); this.fieldElement.type = ‘text‘; this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }, attachEvents: function() { var that = this; this.staticElement.addEventListener(‘click‘, function() { that.convertToEditable(); }, false); this.saveButton.addEventListener(‘click‘, function() { that.save(); }, false); this.cancelButton.addEventListener(‘click‘, function() { that.cancel(); }, false); }, convertToEditable: function() { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘inline‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }, save: function() { this.value = this.getValue(); this.convertToText(); }, cancel: function() { this.convertToText(); }, convertToText: function() { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘inline‘; this.setValue(this.value); }, setValue: function(value) { this.fieldElement.value = value; this.staticElement.innerHTML = value; }, getValue: function() { return this.fieldElement.value; } };
function EditInPlaceField(id, parent, value) { this.id = id; this.value = value || ‘default value‘; this.parentElement = parent; this.createElements(this.id); this.attachEvents(); }; augment(EditInPlaceField, EditInPlaceMixin);
var body = document.body; var titleClassical = new EditInPlaceField(‘titleClassical‘, body, ‘Title Here‘);
function EditInPlaceArea(id, parent, value) { this.id = id; this.value = value || ‘default value‘; this.parentElement = parent; this.createElements(this.id); this.attachEvents(); };
EditInPlaceArea.prototype.createElements = function (id) { this.containerElement = document.createElement(‘div‘); this.parentElement.appendChild(this.containerElement); this.staticElement = document.createElement(‘p‘); this.containerElement.appendChild(this.staticElement); this.staticElement.innerHTML = this.value; this.fieldElement = document.createElement(‘textarea‘); this.fieldElement.value = this.value; this.containerElement.appendChild(this.fieldElement); this.saveButton = document.createElement(‘input‘); this.saveButton.type = ‘button‘; this.saveButton.value = ‘Save‘; this.containerElement.appendChild(this.saveButton); this.cancelButton = document.createElement(‘input‘); this.cancelButton.type = ‘button‘; this.cancelButton.value = ‘Cancel‘; this.containerElement.appendChild(this.cancelButton); this.convertToText(); }; EditInPlaceArea.prototype.convertToEditable = function () { this.staticElement.style.display = ‘none‘; this.fieldElement.style.display = ‘block‘; this.saveButton.style.display = ‘inline‘; this.cancelButton.style.display = ‘inline‘; this.setValue(this.value); }; EditInPlaceArea.prototype.convertToText = function () { this.fieldElement.style.display = ‘none‘; this.saveButton.style.display = ‘none‘; this.cancelButton.style.display = ‘none‘; this.staticElement.style.display = ‘block‘; this.setValue(this.value); };
augment(EditInPlaceArea, EditInPlaceMixin);
var AreaObject = new EditInPlaceArea(‘AreaObject‘, body, ‘多行文本框默认值‘);
标签:
原文地址:http://www.cnblogs.com/oadaM92/p/4353875.html