zoukankan      html  css  js  c++  java
  • javascript 继承(转)

         javascript继承一直不好理解,每次遇到了看了似乎懂了,但是没有彻底研究过而且遇到一次忘记一次,这次想彻底的解决掉,用最简单直白的阐述。引入了前辈的一些看法,进行了收集加工整理。
    用百度脑图做了整理

    一,javascript中继承的由来

    1-1.javascript的出现

         javascript出现是为了增强用户和浏览器之间的交互。比如,如果网页上有一栏"用户名"要求填写,浏览器就无法判断访问者是否真的填写了,只有让服务器端判断。如果没有填写,服务器端就返回错误,要求用户重新填写,这太浪费时间和服务器资源了。
    当时javascript的作者Brendan Eich受到当时面向对象编程的影响,主要是Java的影响,Javascript里面所有的数据类型都是对象(object)。这时候,他要考虑一个问题,javascript到底需不需要继承?

    1-2.Brendan Eich的选择

         javascript中是没有“类”这个概念的,new 后面不是面向对象编程中的“类”,而是构造函数。如例:

    function DOG(name){
        this.name = name;
    }
    //对这个构造函数使用new,就会生成一个狗对象的实例。var dogA = new DOG('大毛');
    alert(dogA.name); // 大毛

    1-3.new运算符的缺点

         用构造函数生成实例对象,有一个缺点,那就是无法共享属性和方法。

    function DOG(name){
        this.name = name;
      this.species = '犬科';
    }
    //生成两个实例对象:var dogA = new DOG('大毛');
    var dogB = new DOG('二毛');
    
    dogA.species = '猫科';
    alert(dogB.species); // 显示"犬科",不受dogA的影响

         每一个实例对象,都有自己的属性和方法的副本。这不仅无法做到数据共享,也是极大的资源浪费。

    1-4.prototype属性的引入

         考虑到这一点,Brendan Eich决定为构造函数设置一个prototype属性。

         这个属性包含一个对象(以下简称"prototype对象"),所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。

         实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分成两种,一种是本地的,另一种是引用的。

    如例:

    function DOG(name){
        this.name = name;
    }
    DOG.prototype = { species : '犬科' };
    
    var dogA = new DOG('大毛');
    var dogB = new DOG('二毛');
    
    alert(dogA.species); // 犬科
    alert(dogB.species); // 犬科//只要修改了prototype对象,就会同时影响到两个实例对象。
    DOG.prototype.species = '猫科';
    alert(dogA.species); // 猫科
    alert(dogB.species); // 猫科

    1-5 总结

         由于所有的实例对象共享同一个prototype对象,那么从外界看起来,prototype对象就好像是实例对象的原型,而实例对象则好像"继承"了prototype对象一样。

    关于第一章节为阮一峰《Javascript继承机制的设计思想》中观点。

    二,构造函数

         构造函数 就是一个普通的函数,通常当函数名 为 大写开头的,我们认为是构造函数,否则 就是普通的方法。

    // 构造函数function A() {
        this.name = 'A Class instance';
    }
    // 普通方法function m1() {
    }
    

    三.Null是原型链的最后一环

    JavaScript只有一种结构:对象。每个对象都有一个内部链接指向另一个对象,这个对象称为原型 (prototype)。那个原型对象也有自己的原型,如此直到某个对象以null作为其原型。null,根据定义,没有原型,作为这种原型链的最后一环而存在。

         尝试用语言去解释

    // 假设有个对象o,其原型链如下所示:// var o = {a: 1, b: 2} ---> {b: 3, c: 4} ---> null// 'a'和'b'是o的自有属性。
    
    // 本例中,someObject.[[Prototype]]指定someObject的原型。// 这完全是一种标记符号(基于ECMAScript标准中所使用的),不可用于脚本中。
    
    console.log(o.a);   // 1// o有一个自有属性'a'吗?是的,其值为1
    
    console.log(o.b);   // 2// o有自有属性'b'吗?是的,其值为2// o的原型也有一个属性'b',但是这里不会被访问。这被称为“属性隐藏”(property shadowing)
    
    console.log(o.c);   // 4// o有自有属性'c'吗?没有,检查它的原型// o.[[Prototype]]有自有属性'c'吗?是的,其值为4。
    
    console.log(o.d);   // undefined// o有自有属性'd'吗?没有,检查其原型// o.[[Prototype]]有自有属性'd'吗?没有,检查其原型// o.[[Prototype]].[[Prototype]]为null,停止搜索,没有找到属性,返回undefined。

    我们用代码去解释

    var o = {a: 1};
    
    // 新创建的对象o有Object.prototype作为其[[Prototype]]// o没有名为'hasOwnProperty'的自有属性// hasOwnProperty是Object.prototype的自有属性。因此o从Object.prototype继承了hasOwnProperty// Object.prototype以null为其prototype。// o ---> Object.prototype ---> null
    
    var a = ["yo", "whadup", "?"];
    
    // 数组继承自Array.prototype(它具有indexOf, forEach等方法)。// 该原型链如下所示:// a ---> Array.prototype ---> Object.prototype ---> null
    
    function f() {
        return 2;
    }
    
    // 函数继承自Function.prototype(它具有call,bind等方法):// f ---> Function.prototype ---> Object.prototype ---> null

    四,参考的资料和笔记:

  • 相关阅读:
    Linux shell脚本学习
    正则表达式 学习-编辑
    新装ubuntu使用vi时方向键不起作用
    vi
    ln
    crontab
    64bit ubuntu 14 04 LTS 安装 google chrome
    64bit ubuntu 14 04 LTS 安装 adobe flash player
    glogin.sql的常用配置
    sql基本语句(一)select
  • 原文地址:https://www.cnblogs.com/akou/p/4469485.html
Copyright © 2011-2022 走看看