聊一聊Javasript继承
程序员文章站
2022-03-26 22:57:00
前前后后已经快写了2年左右javaScript,刚开始只是简单用于一些表单验证和操作dom节点,并没有深入的使用,随着渐渐的深入,开始不想去写重复的代码(懒的开始),从而写简单的继承,封装,抽象等等,最终效果写重复代码少、可用性高(主要:迭代快、代码可以持续使用, 加班 也少 ......
前前后后已经快写了2年左右javaScript,刚开始只是简单用于一些表单验证和操作dom节点,并没有深入的使用,随着渐渐的深入,开始不想去写重复的代码(懒的开始),从而写简单的继承,封装,抽象等等,最终效果写重复代码少、可用性高(主要:迭代快、代码可以持续使用,加班也少)
Demo构造函数声明类function Person(name){ this.name = name; }new生成实例
new生成实例的缺点:无法共享属性和方法,每次new新的实例会开辟新的内存空间,造成极大的资源浪费。
var personA = new Person('小明'); console.log(personA.name);
构造函数的this指向新的实例
如:
function Person(name){ this.name = name; this.sex = '女' } var personA = new Person('小明'); var personB = new Person('小妞'); personA.sex = '男'; console.log(personB.sex); //女
在这里我们该采用声明解决方案呢?设计者很好的解决了这个问题,那么就是prototype属性(包含对象)的引入
prototype属性它的好处是,实例一旦创建,将自动共同持有共享属性和方法,如:
function Person(name){ this.name = name; } Person.prototype.sex = '女'; var personA = new Person('小明'); var personB = new Person('小妞'); console.log(personA.sex); //女 console.log(personB.sex); //女 //证明它们是共享的 Person.prototype.sex = '男'; console.log(personA.sex); //男 console.log(personB.sex); //男
也许在这里你看不出prototype的好处,但是当你有很多方法和属性时,你的运行效率还高嘛?那么:
function Person(name, sex){ this.name = name; this.sex = sex, this.country = '中国', this.show = function(){ console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex); } } var personA = new Person('小明'.'男'); personA.show(); //小明的国籍是是中国,性别:男 var personB = new Person('小妞','女'); personB.show(); //小妞的国籍是是中国,性别:女
感觉似乎没有什么问题,但是personA和personB都包含有country、show属性方法一模一样的内容,这样就造成了空间的浪费,效率也降低了,那么我们可以它们共享属性和方法
function Person(name, sex){ this.name = name; this.sex = sex, } Person.prototype.country = '中国'; Person.prototype.show = function(){ console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex); } var personA = new Person('小明'.'男'); var personB = new Person('小妞','女'); personA.show(); //小明的国籍是是中国,性别:男 personB.show(); //小妞的国籍是是中国,性别:女
配合protorype使用的属性--isPrototypeOf(),hasOwnPrototype(),in
function Person(name, sex){ this.name = name; this.sex = sex, } Person.prototype.country = '中国'; Person.prototype.show = function(){ console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex); } //isPrototypeOf() 判断实例和对象之间的关系 console.log(Person.prototype.isPrototype(personA)) //true console.log(Person.prototype.isPrototype(personB)) //true //hasOwnPrototype() 判断属性是本地属性,还是继承自prototype属性 console.log(personA.hasOwnPrototy('name')) //true console.log(personA.hasOwnPrototy('country')) //false //in 判断是否含有属性,不管本地还是继承prototype console.log('name' in personA) //true console.log('country' in personA) //trueconstructor属性
继续使用前面Person原型对象
function Person(name){ this.name = name; } Person.prototype.sex = '女'; var personA = new Person('小明'); var personB = new Person('小妞'); //新增的实例自动包含有constructor属性 console.log(personA.constructor == Person); //true console.log(personB.constructor == Person); //true
这里也可以使用instanceof判断实例和原型对象之间的关系
console.log(personA instanceof Person); //true console.log(personB instanceof Person); //true常用Object之间“继承”(构造函数继承)(5种)
假设现在有Person和Teacher两个Object,想让Teacher继承Person
//Person对象 function Person(name){ this.name = name; } //Teacher对象 function Teacher(age,sex){ this.age = age; this.sex = sex; }1、:利用构造函数绑定(call或者apply)
function Teacher(age,sex,name){ Person.apply(this,name);//Person.call(this,name); this.age = age; this.sex =sex; }2、:使用prototype,也就是我们前面说prototype属性,修改constructor指向
Teacher.prototype = new Person('xiaoming'); //修改prototy对象原先的值 Teacher.prototype.constructor = Teacher; var teacher1 = new Teacher(19,'女');3、:直接继承prototype
function Person(){} person.prototype.name = "xiaoming"; function Teacher(age,sex){ this.age = age; this.sex = sex; } //Teacher的prototype对象直接指向Person的prototype对象 Teacher.prototype = Person.prototype; Teacher.prototype.constructor = Teacher var teacher1 = new Teacher(19,"女");4、中介new function(){}空对象
var Fn = new function(){}; Fn.prototype = Person.prototype; Teacher.prototype = new Fn(); Teacher.prototype.constructor = Teacher; //扩展封装 function Extend(ChildObj,ParentObj){ var Fn = new function(){}; Fn.prototype = ParentObj.prototype; ChildObj.prototype = new Fn(); ChildObj.prototype.constructor = ChildObj; ChildObj.uber = ParentObj.prototype; //直接指向父对象prototype属性 } //Teacher继承Person Extend(Teacher,Person); var teacher1 = new Teacher(19,'女');5、拷贝继承(完全)
function Extend(ChildObj, ParentObj) { var p = ParentObj.prototype; var c = ChildObj.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; } //Teacher继承Person Extend(Teacher,Person); var teacher1 = new Teacher(19,'女');非构造函数“继承”(3种)
//原始 var Person = { name: '小明' } var Teacher ={ age:19, sex:'女' }
这里我们如何可以让Teacher继承Person
1、:object方法function object(obj){ function Fn(){} Fn.prototype = obj; return new Fn(); } var teacher1 = object(Person); teacher1.age = 19; teacher1.sex = '女';2、:浅拷贝方法
function extendCopy(ParentObj){ var c = {}; for(var i in ParentObj){ c[i] = p[i]; } c.uber = p; return c; } //使用extendCopy var teacher1 = extendCopy(Person); teacher1.age = 19; teacher1.sex = '女';3、:深拷贝方法
function extendDeepCopy(ParentObj,ChildObj){ var ChildObj = ChildObj || {}; for(var i in ParentObj){ if(typeof ParentObj[i] === 'object'){ c[i] = (ParentObj[i].constructor === Array) ? [] : {}; extendDeepCopy(ChildObj[i],ParentObj[i]); }else{ ChildObj[i] = ParentObj[i]; } } return ChildObj; } //使用 var teacher1 = extendDeepCopy(Person1); teacher1.age = 19; teacher1.sex = '女';
本文版权归作者共有,欢迎转载,须保留此段声明,并给出原文链接,谢谢!
上一篇: Hazelcast分布式
下一篇: SGML/HTML/XML之间的关系