这章主要学习对象、原型、原型链和继承,比较核心,所以单独整理这一章的内容。

  理解对象:一组名值对,值可以是数据或函数。

属性类型:1数据属性:包含一个数据值的位置。在这个位置可以读取和写入值,4个描述其行为的特性:

[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认true;

[[Eenmuerable]]表示能否通过for-in循环返回属性,默认true;

[[Writable]]表示能否修改属性的值,默认true;

[[value]]:包含这个属性的值。读取属性的时候,从这个位置读,写入属性值的时候,把新值保存在这个位置,默认undefined.

要修改属性默认的特性,必须使用ECMAScript的Object.defineProperty()方法 Object.defineProperty(Person(对象名),"name属性",{

writable:false,value:...

})

2访问器属性:不包含数据值;包含一对getter和setter函数(不是必须),在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性的时候,会调用setter函数并传入新值,这个函数负责决定如何处理数据。

[[Configurable]]表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性,默认true;

[[Eenmuerable]]表示能否通过for-in循环返回属性,默认true;

[[get]]在读取属性时调用的函数,默认undefined

[[set]]在写入属性时调用的函数,默认undefined

访问器属性不能直接定义,须使用ECMAScript的Object.defineProperty()方法

var book={

_year:2004,

edition:1

}

Object.property(book,"year",{

get:function(){return this.year},

set:function(newValue){if(newVlaue>2004){this._year=newValue;this.edition+=newValue-2004;}}

})

book.year=2005;

alert(book.edition);

6.2创建对象:

  1工厂模式:用函数来封装以特定接口创建对象的细节    

    function creatPerson(name,age,job){
      var o=new Object();
        o.name=name;
        o.age=age;
        o.job=job;
        o.sayName=function(){
        alert(this.name);
      };
      return o;
    }
  var person1=creatPerson('zhangfei',29,'killer');
  var person2=creatPerson('guanyu',30,'killer');

2构造函数模式:创建自定义的构造函数,从而定义自定义对象类型的属性和方法

    function Person(name,age,job){
      this.name=name;
      this.age=age;
      this.job=job;
      this.sayName=function(){
        alert(this.name);
      };
    }
    var person1=new Person('zhangfei',29,'killer');
    var person2=new Person('guanyu',30,'killer');

    特点:没有显式的创建对象,直接将属性和方法赋给了this对象,没有return语句。

    创建Person新实例:1创建一个新对象,2将构造函数的作用域赋值给新对象(this指向了这个对象);3执行构造函数中的代码(为新对象添加属性)4返回新对象

    存在问题:每个方法都要在每个实例上重新创建一遍(我的理解是每创建一个实例,实际上构造函数中的方法都是重新执行,创建了新的函数)

    解决方案:原型模式

    原型模式:重点中的重点.利用书中的图示,可以很好地理解,自己画一遍可以了。

    1 原型对象:只要创建新函数,就会为该函数创建一个prototype属性,这个属性指向函数的原型对象。所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性指向prototype属性所在函数

   创建了自定义的构造函数之后,其原型对象默认只会取得constructor属性,当调用构造函数创建一个新实例后,该实例的内部包换一个指针[[Prototype]],指向构造函数的原型对象。(可以在Chrome浏览器中看到,即_proto_),这个连接存在于实例和构造函数的原型对象之间,而不存在于实例和构造函数之间。

  可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系。                       Person.prototype.isPrototypeOf(person1)

   Object.getPrototypeOf(person1)方法可以返回[[prototype]]的值。

当代码读取某个对象的属性时,会执行一次搜索,目标是具有给定名字的属性,搜索首先从对象实例本身开始,找到则返回,找不到则继续搜索指针指向的原型对象,如果在原型对象中找到,则返回

(实例中添加一个属性,如果与实例原型对象中的属性同名,会屏蔽但不会修改原型对象中的值)

使用hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中,来自实例true,来自原型:false

    e: function Person() { }

      Peraon.protopyty = {

          constructor:Person, //这里使用字面量来简写,本质上重写了prototype对象,这里定义它指向Person构造函数

         name: '张飞',

        age: 29,

         job: 'killer',

    sayName: function () { }

    }

    var person1 = new Person();

    var person2 = new Person();

    person1.hasOwnPorpertype('name')//false

    person1.name = '李典';

    person1.hasOwnPorpertype('name')//true

    console.log(person1.name);//李典

    console.log(person2.name);//张飞

    delete person1.name;

    console.log(person1.name);//张飞

原型与in操作符:单独使用in:对象能够访问属性就返回true  alert('name' in person1) //true

    问题:原型对象中的属性被所有实例共享,对于包含引用类型值的属性来说,就存在问题了,一个实例中属性变,导致都变。

组合使用构造函数模式和原型模式

  构造函数用于定义实例属性,原型模式用于定于方法和共享的属性e:

             
function 
Person(name,skill,country) {

this.name=name;

this.skill=skill;

this.country=country;

this.member=["刘封","刘婵"];

}

Person.prototype={

constructor:Person,

sayUseSkill:function () {

alert(this.skill);

}

}

var person1=new Person('马超','铁骑','蜀国');

var person2=new Person('刘备','仁德','蜀国');

person1.member.push('关羽');

console.log(person1.member);

console.log(person2.member);

console.log(person1.member===person2.member);//false

console.log(person1.sayUseSkill===person2.sayUseSkill);//true

动态原型模式:在构造函数中初始化原型对象

    function 
Person(name,skill,country) {

this.name=name;

this.skill=skill;

this.country=country;

if(typeof this.sayCountry !=undefined){

Person.prototype.sayCountry=function () {

alert(this.country);

};

}

}

var
friend=new Person('张飞','咆哮','蜀国');

friend.sayCountry();

6.3 继承 涉及到原型链

  原型链:(继承:原型对象等于另一个类型的实例) 思想:利用原型让一个引用类型继承另一个引用类型的属性和方法

  首先先滤清构造函数、原型对象、实例之间的关系:每个构造函数有一个原型对象(构造函数有一个prototype属性指向原型对象),而原型对象有一个constructor属性指向构造函数,而实例中有一个内部属性(指针)[[Prototype]]指向原型对象

    如果然原型对象等于另一类型的实力,那么这个原型对象将包含指向另一个原型对象的指针,然后(另一个原型对象)又是第三个函数的实例,那么依然如上述,层层递进,就构成了原型链。虽然看着绕,但是动手画一画就很明晰了(我的理解是父函数的实例是子函数的原型)。

  例子:(添加了注释,这样看着图非常容易理解)  

    //父函数,他的实例中有[[Prototype]]属性和自定义的property属性

    function SuperType(){

    this.property=true;

    }

    //在SuperType原型对象中添加getSuperValue方法

    SuperType.prototype.getSuperValue=function(){

    return this.property

      }

    //子函数,构造函数SubType,它的实例中有[[Prototype]]属性和自定义的subproperty属性

    function SubType(){

    this.subproperty=false;

      }

    //继承了SuperType (原型链)

    SubType.prototype=new SuperType();

    //在SubType原型对象中添加getSubValue方法

    SubType.prototype.getSubValue=function(){

return tis.subproperty;

    };  

    var insatance=new SubType();

    alert(insatance.getSuperValue()); //true

谨慎的定义方法:子类型有时候需要重写超类型中的某个方法,或者需要添加超类型中不存在的某个方法。给原型添加方法的代码一定要放在替换原型的语句之后。

  存在问题:还是引用类型值会改变,因为实例共享属性。

  经典继承(借用构造函数)

  在子类构造函数的内部调用超类构造函数

     相当于把父类的属性实例化到子类中?Java中的super() 存在疑问

    function SuperType(){

  this.colors=['red','blue','green'];

    }

    function SubType(){

    //继承了SuperTYpe

    SuperType.call(this);

     }

    var insatance1=new SubType();

    insatance1.colors.push('black');

    alert(insatance1.colors);// 'red,blue,green,black'

    var insatance2=new SubType();

   alert(insatance2.colors);//'red,blue,green'

1传递参数:

      借用构造参数可以在子类型构造参数中向超类型构造参数传递参数

      function SuperType(name){

this.name=name;

      }

      function SubType(){

    //继承了SuperTYpe,同时还传递了参数

    SuperType.call(this,'赵云');

    //实例属性

    this.age=29;

    }

    var insatance=new SubType();

    alert(insatance.name); //赵云

    alert(insatance.age); //29

为了确保SuperType构造函数不会重写子类型的属性,可以在调用超类型构造函数之后,再添加应该在子类型中定义的属性。

问题:方法都在构造函数中定义超类型中的方法对子类型不可见。

  组合继承

    原型链和构造函数技术组合到一起,使用原型链实现对原型属性和方法的继承,借用构造函数来实现对实例属性的继承。这样通过在原型上定义方法实现了函数的复用,有能够保证每个实例都有它自己的属性

    原型继承:方法可以,实例属性无法继承; 借用构造函数:实例属性可以,方法不行。 一起用,完美。

      function SuperType(name){

  this.name=name;

  thi.colors=['red','blue','green'];

    }

    SuperType.prototype.sayName=function(){

  alert(this.name);

    };

    function SubType(name,age){

  //继承属性

  SuperType.call(this,name);

  this.age=age;

    }

     //继承方法

  SubType.prototype=new SuperType();

  SubType.prototype.sayAge=function(){

  alert(this.age);

   }

  var instance1=new SubType('zhaoyun',29);

  instance1.colors.push('black');

  alert(instance1.colors); //'red,blue,green,black'

  instance1.sayName();//zhaoyun

  instance1.sayAge();//29

  var insatance2=new SubType('诸葛瑾',25);

  alert(instance2.colrs);'red,blue,green'

  instance22.sayName();//诸葛瑾

  instance2.sayAge();//25

原型式继承

  object()方法  function object(o){

    function F(){};

    F.prototype=o;

    return new F();}

对传入的对象执行了一次复制,在object()函数内部,先创建了一个临时性的构造函数,然后将传入的对象最为这个构造函数的原型,最后返回了这个临时了新的一个新实例。

  var person={

name:'张飞',

friends:['马超','刘备','赵云'];

}

var anothersPerson=object.create(person);

anothersPerson.name='孙权';

anothersPerson.friends.push('鲁肃');

var yetAnothersPerson=object.create(person);

yetAnohersPerson.name='曹操';

yetAnothersPerson.friends.push('关羽');

alert(person.friends);//马超,刘备,赵云,鲁肃,关羽

寄生式继承

使用hasOwnProperty()方法可以检测一个属性是存在于实例中还是存在于原型中,来自实例true,来自原型:false

e: function Person() { }

Peraon.protopyty
= {

name: '张飞',

age: 29,

job: 'killer',

sayName: function () { }

}

var person1 = new Person();

var person2 = new Person();

person1.name
= '李典';

console.log(person1.name);

console.log(person2.name);

delete person1.name;

console.log(person1.name);

寄生组合式函数

  组合继承模式问题:会调用两次超类型构造函数,一次是在创建子类型原型的时候,另一次是在子类型构造函数内部,虽然子类型最终包含超类型对象的全部实例属性,但是在调用子类型构造函数时重写了这些属性。

   function SuperType(name){
    this.name=name;
    this.colors=['red','blue','green'];
  }
  SuperType,prototype.sayName=function(){
    alert(this.name);
  };
  function SubType(name,age){
  SuperType.call(this.name);//
第二次调用SuperTyper()构造函数,相当于java中的super()?又在新对象上创建了实例属性name 和colors,因此屏蔽了原型中的两个同名属性。
  this.age=age;
  }
  SubType.prototype=new SuperType(); //
第一次调用SuperType()构造函数,Subprototype会得到两个属性:name,colors,是父函数实例属性,位于子函数原型中
  SubType.prototype.constructor=SubType;
  SubType.prototype.sayAge=function(){
    alert(this.age);
  };

解决方案:巧用原型式继承,传入对象由父类型对象变为父类型对象的原型。

JavaScrip之对象与继承的更多相关文章

  1. js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } Class ...

  2. 对象的继承关系在数据库中的实现方式和PowerDesigner设计

    原文:对象的继承关系在数据库中的实现方式和PowerDesigner设计 在面向对象的编程中,使用对象的继承是一个非常普遍的做法,但是在关系数据库管理系统RDBMS中,使用的是外键表示实体(表)之间的 ...

  3. 类和对象:继承 - 零基础入门学习Python038

    类和对象:继承 让编程改变世界 Change the world by program 上节课的课后作业不知道大家完成的怎样?我们试图模拟一个场景,里边有一只乌龟和十条鱼,乌龟通过吃鱼来补充体力,当乌 ...

  4. #JavaScript对象与继承

    JavaScript对象与继承 JavaScript是我在C语言之后接触的第二门编程语言,大一暑假的时候在图书馆找了一本中国人写的JavaScript程序设计来看.那个时候在编程方面几乎还是小白,再加 ...

  5. Javascript学习6 - 类、对象、继承

    原文:Javascript学习6 - 类.对象.继承 Javasciprt并不像C++一样支持真正的类,也不是用class关键字来定义类.Javascript定义类也是使用function关键字来完成 ...

  6. (79)Wangdao.com第十五天_JavaScript 对象的继承_prototype原型对象_封装_函数式编程

    javascript 内置了许多 function 函数(){...} js 执行首先就会执行自己内置的函数定义 (function Function.function Object) 对象的继承 大 ...

  7. Javascript实现对象的继承

    在Java和C#中,你可以简单的理解class是一个模子,对象就是被这个模子压出来的一批一批月饼.压个啥样,就得是个啥样,不能随便动,动一动就坏了.而在Javascript中,没有模子,月饼被换成了面 ...

  8. 关于js的对象原型继承(一)

    javascript中,对象的继承是通过原型去继承. 可以这样理解:js中的对象,包含的除了属性和方法,还有一个最基本的原型__proto__对象.这个原型__proto__指向谁,这个对象就继承谁. ...

  9. js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } ClassA ...

随机推荐

  1. python脚本基础总结

    1. 注释 ①单行注释:#单行注释 ②多行注释: ''' 三个单引号,多行注释符 ''' ③中文注释:#coding=utf-8 或者 #coding=gbk 2.输入输出 ① 输入:  3.0后的p ...

  2. JS实现div动态水平垂直居中

    在做页面的过程中,在很多地方都会遇到元素需要水平垂直的居中这个问题,之前总是去网上搜别人的代码,今天仔细研究了一下,分享给大家,先写一个简单的例子: <div class="mui-c ...

  3. MSMQ消息队列 用法

    引言 接下来的三篇文章是讨论有关企业分布式开发的文章,这三篇文章筹划了很长时间,文章的技术并不算新,但是文章中使用到的技术都是经过笔者研究实践后总结的,正所谓站在巨人的肩膀上,笔者并不是巨人,但也希望 ...

  4. zendstudio快捷键复制行Ctrl+Alt+向下无效的解决方法

    今天不断地在百度输入类似"zendstudio快捷键复制行Ctrl+Alt+向下无效"这样的关键字,里面搜索到的内容都是在说系统的显卡驱动Ctrl+Alt+方向键和ZendStud ...

  5. Word设置首页不同

    Sub 批量格式设置()  '此代码为指定文件夹中所有选取的WORD文件的进行格式设置 Dim MyDialog As FileDialog, vrtSelectedItem As Variant, ...

  6. html5 history api

    1.html5 history api适用场景,个人理解最大的用处是配合ajax使用,使ajax拥有回退.前进的用户体验. 2.代码(dive into html5中的一个小例子) 1)fer.htm ...

  7. 面试中遇到的iOS笔试题

    1.浅复制和深复制的区别? 2.类别的作用(category)?继承和类别在实现有何区别? 3.类别(category)和类扩展(extension)的区别. 4.obc中的协议和java中的接口概念 ...

  8. Delphi JCL JEDI使用 jclDebug

    开源 https://github.com/project-jedi/jcl jclDebug 下载jcl,还要下载https://github.com/project-jedi/jedi里的2个in ...

  9. php 文件锁

    当写为LOCK_EX锁 且 读为LOCK_SH锁时最为妥当,经测试,这时情况如下: 1, 先运行w.php,马上支行r.php 后 程序会先等写入后再读取 2, 先运行r.php,再马上支行w.php ...

  10. 关于设置anroid系统时间

    我最近在做一个项目需要设置android系统时间,设置android 时间往往缺少权限,看到http://blog.csdn.net/kakaxi1o1/article/details/3687278 ...