文档章节

Javascript 面向对象编程

_World
 _World
发布于 2015/01/09 10:15
字数 1617
阅读 4
收藏 0

最原始的类和对象声明方法

类声明如下所示:

var Cat = {
    name : '',
    color : ''
  }

如果我们要声明Cat类的实例的话,则代码如下所示:

  var cat1 = {}; // 创建一个空对象
    cat1.name = "大毛"; // 按照原型对象的属性赋值
    cat1.color = "黄色";
  var cat2 = {};
    cat2.name = "二毛";
    cat2.color = "黑色";

但是这样有两个显著的缺点:

    如果多生成几个实例,写起来就非常麻烦;

    实例与原型之间,没有任何办法,可以看出有什么联系。

构造函数模式创建对象

事实上构造函数跟普通函数没有任何区别,唯一的技巧在于内部使用了this变量,这样对对构造函数使用new运算符,就能生成实例,然后this变量会绑定在实例对象上。

那么上述的代码我们可以使用构造函数这样来写:

function Cat(name,color){//构造函数
    this.name=name;
    this.color=color;
    
       this.type = "猫科动物";
     this.eat = function(){alert("吃老鼠");};
  }
//声明类实例
  var cat1 = new Cat("大毛","黄色");
  var cat2 = new Cat("二毛","黑色");//cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。
    console.log(cat1.constructor == Cat); //true
  console.log(cat2.constructor == Cat); //true
//Javascript还提供了一个instanceof运算符,验证原型对象与实例对象之间的关系。
    console.log(cat1 instanceof Cat); //true
  console.log(cat2 instanceof Cat); //true

大家有没有想过构造函数的缺点,那就是资源浪费。如上述代码所示,那么每个对象都会有一个属于自己的name和color属性,对于属性这样是无可厚非,可是如果是方法呢,每个对象都会有一个属于自己的但实现相同功能的方法,这样难道不是大大的资源浪费吗?

大家注意到上面的代码“cat1.constructor == Cat” 

解释一下哦:任何一个prototype对象都有一个constructor属性,指向它的构造函数。每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性。


构造函数绑定,即用call(apply)把父对象的this指向改为子对象,

Prototype模式

    Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这样我们就可以把所有的属性放在构造函数当中,而把所有的方法放在Prototype上。

    所以上述代码可以如下使用:

function Cat(name,color){//声明类
    this.name = name;//所有属性都放在构造函数里面
    this.color = color;
  }
//所有方法都放在prototype链上
 Cat.prototype.type = "猫科动物";
 Cat.prototype.eat = function(){alert("吃老鼠")};
  var cat1 = new Cat("大毛","黄色");
 var cat2 = new Cat("二毛","黑色");
 console.log(cat1.eat == cat2.eat); //true  这个时候不同实例共享原型链上的同一个方法

    如何检测对象和实例的关系呢,有如下三种方法:

console.log(Cat.prototype.isPrototypeOf(cat1)); //true  
alert(cat1.hasOwnProperty("name")); // true
alert("name" in cat1); // true

    hasOwnProperty和in唯一的区别就在于如果是从原型链上继承的属性in也会返回true,而hasOwnProperty则返回false。

    上面不只是介绍说如何声明类以及实例化类的对象,那下面讲讲各个类如何继承。

    介绍如下几种:

    构造函数继承

    prototype模式继承

    拷贝继承

    构造函数继承

  function Animal(){//父类
    this.species = "动物";
  }
      function Cat(name,color){//子类
            Animal.apply(this, arguments);//这句话就实现了继承  使用call或apply方法,将父对象的构造函数绑定在子对象上
    this.name = name;
    this.color = color;
  }

prototype模式继承

  function Animal(){//父类
    this.species = "动物";
  }
      function Cat(name,color){//子类        
    this.name = name;
    this.color = color;
  }    
  Cat.prototype = new Animal();
  Cat.prototype.constructor = Cat;

    prototype模式继承的经典在于让子类的prototype指向父类的实例,因为每个prototype对象都会有一个constuctor来指向它的构造函数,而上述的“Cat.prototype = new Animal();”这句代码就使得prototype的constructor属性指向了Animal,大家想想这样不就乱套了吗,所以才用了“Cat.prototype.constructor = Cat;”来修正

    大家想想上述代码有什么缺点,那就是每个子类都必须声明一个父类的实例,这样启不是资源的浪费。所以我们如果使用prototype模式来继承一般会使用如下方法。

function extend(Child, Parent) {
    var F = function(){};//声明一个空对象
    F.prototype = Parent.prototype;//把空对象的原型链指向父对象的原型链  事实上F类就相当于Parent类
    Child.prototype = new F();//依旧子对象的prototype为父对象的实例   只不过这时是一个空对象而已  节省了资源
    Child.prototype.constructor = Child;//修正原型链
    Child.uber = Parent.prototype;//在子对象上打开一条通道,可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质
}
//使用的时候如下所示
extend(Cat,Animal);//Cat继承Animal
var cat1 = new Cat("大毛","黄色");//实例化对象

拷贝继承

  function extend(Child, Parent) {
    var p = Parent.prototype;
    var c = Child.prototype;
    for (var i in p) {
      c[i] = p[i];
      }
    c.uber = p;
  }

    拷贝继承的方式有些类似其它语言如C#的思想,循环遍历属性然后给另外一个对象赋值,似乎这样也能实现继承,但是大家有没有想过上述方法的弊端,如果属性是引用类型的呢,那是不是又乱了,修改了一个实例的引用类型的属性就导致其它对象的相应属性的值改变,这样的继承只能说是不彻底的。那么我们应该怎么样实现深度拷贝继承呢

  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;
  }

    事实上JQuery库就是使用的深拷贝继承,大家可以想想为什么,因为拷贝继承很适合传递参数,大家想想编写jQuery插件时,写一些配置参数的时候是不是如下使用,结合想想会不会明白些许

    options = $.extend({
        name: 'Default Name',
        age: 22,
        man: true
    }, options);

object()方法继承

  function object(o) {
    function F() {}//临时声明一个构造函数  使这个构造函数的PROTOTYPE属性指向父对象,从而使得子对象与父对象连在一起,然后生成一个实例并返回把子对象的prototype属性,
    F.prototype = o;
    return new F();
  }


本文转载自:

_World
粉丝 0
博文 8
码字总数 0
作品 0
西安
私信 提问
分享51本关于JavaScript方面的学习书籍(免费下载)

分享51本关于JavaScript方面的学习书籍(免费下载) 1、JavaScript面向对象15分钟教程 2、原型、作用域、闭包的完整解释 3、Javascript面向对象特性实现(封装、继承、接口) 4、JavaScript面向...

邓剑彬
2012/12/02
1K
12
js面向对象的一些初级知识总结~~

javascript作为一门解释性脚本语言,有着其独特的魅力.既具有函数编程的特性,又具有面向对象的特征.以前的开发中,大多是使用了javascript的函数式编程,最近,发现其的面向对象也有一定的优势,...

乔康007
2013/02/24
170
0
好程序员web前端培训分享学习JavaScript

好程序员web前端培训分享学习JavaScript,我试着总结自己学习JavaScript的方法 JavaScript给人那种感觉的原因多半是因为它如下的特点: 1、本身知识很抽象、晦涩难懂,如:闭包、内置对象、D...

好程序员IT
04/09
8
0
是时候谈谈JavaScript面向对象了!(我们什么时候更需要它)

前端技术尤其是JavaScript,经常被后端觉得不是正经编程语言,大多数是因为JavaScript是基于函数的语言,因此潜在上使得它在使用和发展上有所局限。 我记得在90年代末和21世纪初,JavaScrip...

Little heaven
05/14
0
0
细说JavaScript数据类型及转换

细说JavaScript数据类型及转换 JavaScript数据类型 1.Boolean(布尔) 布尔:(值类型)var b1=true;//布尔类型 2.Number(数字) 数值:(值类型)var n1=3.1415926;//数值类型 n1.toFixed...

开元中国2015
2015/07/13
103
1

没有更多内容

加载失败,请刷新页面

加载更多

nginx+tomcat配置https

1、nginx配置https和【proxy_set_header X-Forwarded-Proto $scheme;】 2、java代码: String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServe......

perofu
16分钟前
3
0
必看的Linux系统新手进阶老手心得

不知道从什么时候起,linux这个话题变得越来越普及,成为大家经常讨论的话题。无论在网络上还是实际生活中,竟然很多人都在纠结学习linux的问题。网络上给的答案千千万万,而却还有很多人踌躇...

Linux就该这么学
19分钟前
3
0
Spring Boot 配置元数据指南

1. 概览 在编写 Spring Boot 应用程序时,将配置属性映射到 Java bean 上是非常有用的。但是,记录这些属性的最好方法是什么呢? 在本教程中,我们将探讨 Spring Boot Configuration Proces...

liululee
22分钟前
2
0
foreach查找子类

$list = $menu_model -> menu_list();$parent_list = [];foreach ($list as $v){ if ($v['pid'] == 0) { $parent = $v; foreach ($list as $v1) ......

小小小壮
34分钟前
2
0
基于 HTML5 Canvas 实现的 TP-LINK 电信拓扑设备面板

前言 今天我们以真实的 TP-LINK 设备面板为模型,完成设备面板的搭建,和指示灯的闪烁和图元流动。 先来目睹下最终的实现效果:http://www.hightopo.com/demo/blog_tplink_20170511/index.h...

htdaydayup
40分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部