//将obj2混入到obj1中,也称obj1继承自obj2function mix(obj1,obj2){ for(var k in obj2){ obj1[k] = obj2[k]; }}一般在混入的时候,都是混入的函数,所以考虑深拷贝的机会较少,在jq框架中,有一个方法叫 extend ,该方法实现 jq 中的混入。该方法具有的特征是:① 将多个对象混入到一个对象中mix ( dest, obj1, obj2, obj3, ... )② 实现深拷贝③ 实现原型式继承④ 实现对象的构造(不使用构造函数创建对象)(3)在实际开发的时候,常常是这两种方法混合使用(混合式继承)在构造函数的原型上使用混入,那么原型对象就具有了很多方法属性等成员,那么构造函数的实例对象就自动的继承了这些成员,而且还有共享。// 1.准备一个构造函数function Role( name ) { this.name = name;}// 2.在原型中准备一个 extend 方法Role.PRototype.extend = function ( obj ) { // 将 obj 的成员混入到 原型对象中 for ( var k in obj ) { this[ k ] = obj[ k ]; }};// 3.尽情的扩展( 继承 )// 为了简单这么处理Role.skill = Role.prototype;// 法术攻击Role.skill.extend({ fireBall: function () { console.log( '火球之术' ); }, bigFireBall: fucntion () ...});// 雷电 thunderRole.skill.extend({ qidoli: fucntion() { .... } ... });// 增加技能Role.skill.extend({ iceSkill: fucntion() { .... } ... });// 4.创建角色var sasigi = new Role( 'f' );2. 经典继承语法
在ES5出现以前,就有人模拟了继承的方式,就是使用一个对象,创建出另一个对象出来,保证被创建出来的对象的原型就是这个指定的对象。//调用该函数,可以创建一个继承自参数给定的对象的对象function create(baSEObj){ function F(){} F.prototype = baseObj; return new F();}//可以创建一个对象,该对象继承自一个数组var myArray = create( [] );//可以将myArray作为数组使用,是真数组/*增*/myArray.push('第一个被push进来的数据');myArray.unshift('第二个被unshift加入的数据');myArray[myArray.length++]='利用数组索引加入的数据';/*删*/myArray.pop();//删并返回最后一个myArray.shift();//删并返回第一个myArray.splice(1,1);/*改*/myArray[1] = '哈哈哈';myArray.splice(1,1,'a','b','c');//从下标为1开始,删掉1个元素,把后面的数据插入此位置/*查*/var i1 = myArray.indexOf('b');在较新的 ES5 的规范中已经内置了该算法,使用 Object.create 来实现该功能。所谓的简单对象,首先要保证简单,没有多余的复杂数据:var obj = Object.create(null);console.log(obj); //空的简单对象,里面什么都没有没有写构造函数,obj 就是 Object 创建出来的。var obj = Object.create(base);//此时是一种特殊情况,obj 没有构造函数,是内部创建的3. 比较高级的继承方法
Object.create(base) => sub该方法有两大缺点:① 没有构造函数,无法复用② 没有扩展,创建的子对象与父对象其实一模一样,只是层级结构不同我们需要提供一个函数,满足以下功能:① 可配置构造函数,由用户决定构造函数应该如何定义② 可返回构造函数③ 应该有继承要求可以配置,其实就是可以自己定义属性和方法function createClass( options ){ return function(){ //这个函数就应该是最终的构造函数 }}由于需要重新配置构造函数的内容与原型,也要配置方法,可以让 options 中必须带有方法数据,因此代码可以修改为另一种形式:function createClass( options ){ //要求 options中必须包含 constructor 和 methods //constructor是构造函数,它需要被返回 //methods是该对象应该具有的方法,应该将方法加到原型中 options.constructor.prototype = options.methods; return options.constructor;}简单优化后:function createClass( options ){ var ctr = options.constructor; ctr.prototype = options.methods;//用替换原型的办法 return ctr;}使用:属性应该放在实例对象中,方法应该放在原型中。因此,两个参数,第一个参数用于配置实例对象的成员,第二个参数用于描述原型。var Person = createClass({ constructor: function(name,age,gender){ this.name = name; this.age = age; this.gender = gender; }, methods: { sayHello: function(){ console.log( '你好,我是'+ this.name ); }, run: function(){ console.log( '你好,'+ this.name + '在跑' ); } }});var p = new Person('jim', 19, '男');p.sayHello();p.run();此时已经有Person了,希望再派生一个Student出来应该提供需要继承的目标(对象?函数?)实现如下形式:那么将需要继承的对象传入要求options提供同一个base属性,表明需要继承谁代码中的ctr的原型应该由base提供
function createClass( options ){ var ctr = options.constructor, base = options.base || Object.prototype; ctr.prototype = Object.create(base);//如果直接把base赋给原型,会出bug,派生对象中增加的东西在原型对象中也会增加 //方法的加入 for(var k in options.methods){ ctr.prototype[k] = options.methods[k]; } return ctr;}正确的(ctr.prototype = Object.create(base);):错误的(ctr.prototype = base;):
新闻热点
疑难解答