关闭

[置顶] 聊一聊Javasript继承

标签: javascript
110人阅读 评论(1) 收藏 举报
分类:

  前前后后已经快写了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)  //true

constructor属性

继续使用前面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 = '女';

本文版权归作者共有,欢迎转载,须保留此段声明,并给出原文链接,谢谢!

0
0
查看评论

聊一聊 Android 6.0 的运行时权限

聊一聊 Android 6.0 的运行时权限 权限一刀切 棉花糖运行时权限 权限的分组 正常权限 正常权限列表 特殊权限 请求SYSTEM_ALERT_WINDOW 请求WRITE_SETTINGS 危险权限 必须要支持运行时权限么 不支持运行时...
  • u011277123
  • u011277123
  • 2016-08-12 14:18
  • 484

茶余饭后:聊一聊那些神一样的程序员们(2)

接上一篇 茶余饭后:聊一聊那些神一样的程序员们 这一篇主要聊一聊安德斯·海尔斯伯格(Anders Hejlsberg ),他没有获得过图灵奖, 在名气上比不上前面几位,但也是另外一个传奇。 其实安德斯还真的和图灵奖有那么一点点联系,故事需要从Pascal 这门曾经大红大紫的...
  • nylx
  • nylx
  • 2013-07-01 13:23
  • 2048

频率学派还是贝叶斯学派?聊一聊机器学习中的MLE和MAP

作者:夏飞Google | 软件工程师量子位 已获授权编辑发布转载请联系原作者本文作者夏飞,清华大学计算机软件学士,卡内基梅隆大学人工智能硕士,现为谷歌软件工程师。在这篇文章中,他探讨了机器学习中的MLE和MAP两大学派的争论。频率学派 - Frequentist - Maximum Likelih...
  • yH0VLDe8VG8ep9VGe
  • yH0VLDe8VG8ep9VGe
  • 2018-01-07 00:00
  • 70

时间共享经济OR荷尔蒙的马甲?为什么2017年,直播平台都在推“一对一”密聊?

编者按:本文来自微信公众号“今日网红”(ID:zhhjrwh),作者:王小红,36氪经授权发布。 当你还在直播间当围观群众时,主播已经将私人时间给了专属用户。 不经意间,曾经火遍早期PC端直播时代的“一对一”直播,又悄悄席卷移动直播界。 6月,陌陌上线“一对一”直播板块——“快聊”;9月,YY...
  • bKMk01MZ3w
  • bKMk01MZ3w
  • 2017-12-14 07:30
  • 127

Python陷阱:为什么不能用可变对象作为默认参数的值

上次分享过一篇关于图解Python变量与赋值的文章,今天接着这个话题继续聊一聊关于赋值的一些坑。先来看一道题目: >>> def func(numbers=[], num=1): ... numbers.append(num) ... return numbe...
  • weixin_40539892
  • weixin_40539892
  • 2018-01-26 14:02
  • 46

Android Studio的相关设置信息笔记

1、Android Studio不区分大小写android studio默认情况下是区分大小写的,所以在编写代码的时候,必须要切换大小写才会有代码提示。取消大小写区分步骤如下: 设置–>Editor–>General–>Code Completion。 2、Android St...
  • zwl5670
  • zwl5670
  • 2016-04-12 13:22
  • 246

Android&融云单聊的实现

1)首先下载融云即时通讯的SDK 导入融云的通讯界面库,以及通讯功能库 IMKit,IMLib 2)在build.gradle中的dependencies中添加 compile project(':IMKit') compile project(':IMLib...
  • m0_37314675
  • m0_37314675
  • 2017-09-19 14:37
  • 966

聊一聊面向对象之继承

继承继承是联结类的层次模型,并且允许和鼓励类的重用,它提供了一种明确表述共性的方法,对象的一个新类可以从现有的类中派生,这个过程叫做类的继承。 新类继承了原始类的特性,新类称为原始类的派生类,也就是子类,而原始类称为子类的基类,也就是父类。 对象的一个新类可以从现有的类中派生,这个过程被称为类继...
  • qq_37248648
  • qq_37248648
  • 2017-04-03 19:55
  • 125

我是这么聊 QQ 的!可以,这很Linux

发布作者:微思网络   发布时间:2016-11-04      支持功能: (11 天前) 1. tab 补全,类似于 irc 软件内的补全命令  2. tab ...
  • xmwswl1
  • xmwswl1
  • 2016-11-04 17:39
  • 283

聊一聊自定义标签

什么是自定义标签 目前我们jsp使用的标签都是HTML的标签,浏览器会解释运行 自定义标签,就是根据需求,自己定义的标签,定义标签的名字、属性、作用等。为什么要自定义标签 jsp文件中,往往需要实现类似的功能,编写很多类似的java代码自定义标签,可以把这些java代码的代码定义成标签,而不必...
  • qq_37248648
  • qq_37248648
  • 2017-05-02 14:51
  • 77
    个人资料
    • 访问:1551次
    • 积分:138
    • 等级:
    • 排名:千里之外
    • 原创:11篇
    • 转载:3篇
    • 译文:0篇
    • 评论:3条
    文章分类