(1)封装

  首先理解构造函数:所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。

  function Cat(name,color){
    this.name=name;
    this.color=color;
  }
  var cat1 = new Cat("大毛","黄色");
  var cat2 = new Cat("二毛","黑色");
  alert(cat1.name); // 大毛
  alert(cat1.color); // 黄色

其中cat1cat2会自动含有一个constructor属性,指向它们的构造函数。

  alert(cat1.constructor == Cat); //true
  alert(cat2.constructor == Cat); //true

构造函数存在一个弊端:浪费内存,比如:

  function Cat(name,color){
    this.name = name;
    this.color = color;
    this.type = "猫科动物";
    this.eat = function(){alert("吃老鼠");};
  }
  var cat1 = new Cat("大毛","黄色");
  var cat2 = new Cat ("二毛","黑色");
alert(cat1.eat == cat2.eat); //false

其中前两个属性name,color是实例独自拥有的,cat1和cat2的name,color是不同的,而type,eat()确是可以共同拥有的,所有可以把共有的方法,属性定义在prototype对象上,如下:

  function Cat(name,color){
    this.name = name;
    this.color = color;
  }   Cat.prototype.type = "猫科动物";
  Cat.prototype.eat = function(){alert("吃老鼠")};   var cat1 = new Cat("大毛","黄色");
  var cat2 = new Cat("二毛","黑色");   alert(cat1.eat == cat2.eat); //true

这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。

(2)继承

  function Animal(){
    this.species = "动物";
  }   function Cat(name,color){
    this.name = name;
    this.color = color;
  }

(Cat要继承Animal)

1.构造函数绑定   

使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行

  function Cat(name,color){
   Animal.apply(this, arguments);
    this.name = name;
    this.color = color;
  }
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物

2. prototype模式

将Cat(子)的prototype指向Animal(父)的实例,那么Cat所创建出来的实例就都继承了Animal

  Cat.prototype = new Animal();
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物

其中第二行代码 Cat.prototype.constructor = Cat; 是因为如果原本constructor本来是指向自己的构造函数cat()的,但是这里被赋值给了new Animal(),换了个新构造函数,所以为了不造成继承链的紊乱,必须手动修改回来

3. 直接继承prototype

Cat不变的属性或方法可以直接写入Animal.prototype,然后Cat.prototype = Animal.prototype直接继承

  function Animal(){ }
  Animal.prototype.species = "动物";   Cat.prototype = Animal.prototype;
  Cat.prototype.constructor = Cat;
  var cat1 = new Cat("大毛","黄色");
  alert(cat1.species); // 动物

这样的好处是,对比方法2中,不用执行和建立Animal()的实例,也省了内存;

这样的缺点是,由于Cat.prototype = Animal.prototype,Cat.prototype和Animal.prototype现在指向了同一个对象,实际上把Animal.prototype对象的constructor属性也改掉了!

4.利用空对象作为中介

用一个F空对象,几乎不占内存,作为中间桥梁,修改Cat的prototype对象,就不会影响到Animal的prototype对象。

  var F = function(){};
  F.prototype = Animal.prototype;
  Cat.prototype = new F();
  Cat.prototype.constructor = Cat;

可以封装成一个函数:

function extend(Child,Parent){
var F = function (){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.construction = Child;
Child.uber = Parent.prototype; //假设一个Child不变的属性uber
} extend(Cat,Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物

5.拷贝继承

把父对象的所有属性和方法,拷贝进子对象

function Animal(){}
Animal.prototype.species = "动物"; function extend2(Child, Parent) {
  var p = Parent.prototype;
  var c = Child.prototype;
  for (var i in p) {
    c[i] = p[i];
  }
  c.uber = p;
} extend2(Cat, Animal);
var cat1 = new Cat("大毛","黄色");
alert(cat1.species); // 动物

(3)非构造函数继承

1.object()方法

  var Chinese = {
    nation:'中国'
  };   var Doctor ={
    career:'医生'
  }

如何使Doctor对象继承Chinese对象?

  function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
  }
  var Doctor = object(Chinese);
  Doctor.career = '医生';
  alert(Doctor.nation); //中国

2.浅拷贝:

只是拷贝基本类型的数据

  function extendCopy(p) {
    var c = {};
    for (var i in p) {
      c[i] = p[i];
    }
    c.uber = p;
    return c;
  }   var Doctor = extendCopy(Chinese);
  Doctor.career = '医生';
  alert(Doctor.nation); // 中国
 Chinese.birthPlaces = ['北京','上海','香港'];

 var Doctor = extendCopy(Chinese);
 Doctor.birthPlaces.push('厦门');

  alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门

  alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门

下面的代码显露出钱浅拷贝的缺点,就是假如父对象的某个属性也是数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。

3.深拷贝

jQuery库使用的就是这种继承方法。

  function deepCopy(p, c) {
    var c = c || {};
    for (var i in p) {
      if (typeof p[i] === 'object') {
        c[i] = (p[i].constructor === Array) ? [] : {};
        deepCopy(p[i], c[i]);
      } else {
         c[i] = p[i];
      }
    }
    return c;
  }   var Doctor = deepCopy(Chinese);   Chinese.birthPlaces = ['北京','上海','香港'];
  Doctor.birthPlaces.push('厦门');   alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门
  alert(Chinese.birthPlaces); //北京, 上海, 香港

以上内容均参考自:

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html

JavaScript面向对象(收集整理)的更多相关文章

  1. javascript收集整理

    //特殊字符去掉 function check(obj){ var test=obj.value.match(/[^A-Za-z0-9]/g);//这条语句表示在输入文本中是否包含不符合要求的字符,如 ...

  2. javascript面向对象精要第三章对象整理精要

    什么是对象的数据属性?什么是对象的访问器属性?[put]方法是默认创建数据属性的,访 问器属性不包含值而是定义了一个单属性被读取时调用的函数(getter)和当一个属性被写入时 调用的函数(sette ...

  3. JavaScript 正则表达收集整理

    JavaScript 正则表达收集整理 //可为空 /^\s*$/ //密码验证,必须且只含有数字和字母,可以拥有英文符号,6-17位 /(?=.{,})(?=.*\d)(?=.*[a-z])[\x2 ...

  4. javascript 面向对象整理

    整理一下js面向对象中的封装和继承. 1.封装 js中封装有很多种实现方式,这里列出常用的几种. 1.1 原始模式生成对象 直接将我们的成员写入对象中,用函数返回. 缺点:很难看出是一个模式出来的实例 ...

  5. 【理论面试篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题

    ##2017.10.30收集 面试技巧 5.1 面试形式 1)        一般而言,小公司做笔试题:大公司面谈项目经验:做地图的一定考算法 2)        面试官喜欢什么样的人 ü  技术好. ...

  6. 【编码题篇】收集整理来自网络上的一些常见的 经典前端、H5面试题 Web前端开发面试题

    编写一个方法 求一个字符串的字节长度假设:一个英文字符占用一个字节,一个中文字符占用两个字节 function GetBytes(str){ var len = str.length; var byt ...

  7. 最常用的PHP正则表达式收集整理

    最常用的PHP正则表达式收集整理 提交 我的评论 加载中 已评论 最常用的PHP正则表达式收集整理 2015-03-20 PHP100中文网 PHP100中文网 PHP100中文网 微信号 功能介绍 ...

  8. 闭包初体验 -《JavaScript面向对象编程指南》

    下面是我对闭包的理解:(把他们整理出来,整理的过程也是在梳理) 参考<JavaScript面向对象编程指南> 1.首先,在理解闭包之前: 我们首先应该清楚下作用域和作用域链 作用域:每个函 ...

  9. 工作流,WEB框架,UI组件网络收集整理

    工作流,WEB框架,UI组件网络收集整理 在博客园上逛了好多年,随手收录了一些工作流,WEB开发框架,UI组件,现在整理一下与大家分享. 由于个人能力与精力有限,望各位园友在评论中补充,我将全部整理到 ...

  10. JavaScript面向对象—深入ES6的class

    JavaScript面向对象-深入ES6的class 前言 在前面一篇中主要介绍了JavaScript中使用构造函数+原型链实现继承,从实现的步骤来说还是比较繁琐的.在ES6中推出的class的关键字 ...

随机推荐

  1. unset与unlink

    unset() -- 释放给定的变量 详见->http://www.kuqin.com/php5_doc/function.unset.html unlink() --删除文件    常用于用户 ...

  2. 【bzoj2761】[JLOI2011]不重复数字

    给出N个数,要求把其中重复的去掉,只保留第一次出现的数. 例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4. Inpu ...

  3. bzoj1087 [SCOI2005][状压DP] 互不侵犯King (状压)

    在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 ...

  4. uva11806

    [题意] n行m列网格放k个石子.有多少种方法?要求第一行,第一列,最后一行,最后一列必须有石子. [题解] 利用容斥原理.可以转到求"第一行.第一列.最后一行.最后一列没有石子" ...

  5. Codeforces Round #425 (Div. 2)C

    题目连接:http://codeforces.com/contest/832/problem/C C. Strange Radiation time limit per test 3 seconds ...

  6. 面向对象编程笔记--static

    通过static方法,提供静态的不需要实例化即可访问的方法或属性.所有的调用者可以使用同一个类(不实例化)或对象(只实例化一次),可以应用的场景: 1)各个调用者共享数据,协同工作. 2)对象只可以实 ...

  7. bootstrap 的可编辑下拉框 jquery.editable-select

    搜了半天发现在某处下载jquery.editable-select需要积分,于是整理出来方便 其他人. 先上下载链接:http://pan.baidu.com/s/1kUXvwlL      pass ...

  8. ubuntu 11.04侧边栏怎么添加图标

    打开想添加的软件,图标会出现在侧边栏,右击之,点Keep In Launcher即可

  9. ConvertUtils.register注册转换器

    当用到BeanUtils的populate.copyProperties方法或者getProperty,setProperty方法其实都会调用convert进行转换 但Converter只支持一些基本 ...

  10. Oracle Database 10g Express Edition系统文件损坏的解决办法

    1.检查错误代码:ora-10010 亦或是ora-10003,上网找响应的解决办法: 异常状态:登陆不上 常用的方法解决 (1)进入Oracle命令行模式 (2)Shutdown immedaite ...