Web前端复习——Javasvript学习(面向对象)

来源:互联网 发布:淘宝店铺装修视频2016 编辑:程序博客网 时间:2024/06/05 16:18

1、面向对象:在程序中都是用一个对象来描述现实中一个具体的东西

现实中任何一个东西都包含属性和功能:

属性——描述一个东西特点的变量,一个值

功能——东西可以执行的操作

(1)什么是对象?

封装多个数据和方法的存储空间

(2)什么是自定义对象?

封装现实中一个东西的属性和功能的存储空间。

注意:

a、现实中东西的属性——对应对象中的属性变量

b、现实中东西的功能——对应对象中的方法


2、创建自定义对象:3种

a、var obj={'属性名1':值1,

    '属性名2':值2,

    '功能名1':function(){...}

    };

js中一切都是对象,所有对象底层都是hash数组

注意:项a方法类似于封装,在程序开发中用的较多。


b、var obj=new Object();    //创建一个空对象

   obj.属性名=值;

   obj.方法名=function(){...this.属性名...}


c、利用构造函数——反复创建相同结构的对象

构造函数:描述一类对象结构的特殊函数

分为2步:

a、定义构造函数

function 构造函数名|类型名(属性参数1,属性参数2){this.属性名=属性参数1;//在当前正在创建的对象中添加一个属性名//赋值为属性参数1的值...this.方法名=function(){...this.属性名...}}


b、利用构造函数创建对象

var obj=new 构造函数名|类型名(属性值1,...)

new:1、创建一个空对象,new obj={  };

     2、用空对象,调用构造函数

构造函数在空对象中添加属性和方法

     3、设置新对象的_proto_指向构造函数的prototype对象

     4、返回新对象的地址


//先定义构造函数function Student(sname,age){     this.sname=sname;     this.age=age;     this.intSelf=function(){           alert("I'm"+this.sname+"I'm"+this.age);     }}var lilei=new Student("Li Lei",12);


(1)属性:如何访问?(2种)

obj.属性名    obj["属性名"]

注意——若访问对象中不存在的属性下标,不会出错,但是会返回undefined



(2)如何判断某个对象是否包含指定成员——3种?

a、obj.hasOwnProperty("");

如果找到,返回true,否则返回false

b、“属性名” in 对象

如果找到,返回true,否则返回false

c、直接使用obj.属性名作为条件:

arr.indexOf==undefined

若不包含,返回undefined——false;

若包含,返回值或function——false


(3)this关键字

方法:如何在方法中,访问当前对象自己

this关键字:运行时,指定正在调用方法的对象(.前的对象)

this本质是window下唯一的一个指针,指向当前正在调用方法的对象。


如何在方法内,访问当前对象自己的属性:this.属性名

注意——

(1)this和定义在哪无关,仅和调用时使用的当前对象有关

(2)所有无主的赋值,都是默认了window对象

(window.)a=100;   //全局变量,this——>window

案例1:在匿名函数中有this关键字

var a=100;(function(){    var a=99;    console.log(this.a);})();    //100

解析——

    由于在匿名函数中用了this关键字,即当前this指向window对象,作为全局变量,所以为“100”,作为全局变量输出。


案例2:在匿名函数中无this关键字

var a=100;(function(){    var a=99;    console.log(a);})();    //99

解析——由于在匿名函数中没有用this关键字,所以不用指向外部全局变量,仅仅是作为局部变量输出,即为“99”。


this关键字——面试题

/*笔试题*///this——>windowvar a=2;//this—->windowfunction fun(){    console.log(this.a);}//this——>windowvar o={a:3,fun:fun};    //创建对象同时,this——>ovar p={a:4};            //赋值同时,this——>po.fun();                //this.o   3   //console.log(o.a);   //3  /*结论——this与它定义在哪无关,this都指向的是当前的对象,上述o.fun(),指向的是“o”,其对应的是3,所以输出3*/      (p.fun=o.fun)();      //2,匿名函数的自调,还是作为全局变量,所以返回2  //p.fun=0x1011  //p={a:4,fun:0x1011}  //返回o.fun中的值! 0x1011(地址)  //(0x1011)(); ——>匿名函数自调 ——>this_window   /*结论——赋值表达式的结果相当于等号右侧表达式的值*/  p.fun();              //4 /*结论——this与它定义在哪无关,this指向当前的对象,即为p*/ 


3、面向对象3大特点:

封装、继承、多态

(1)封装:将描述同一个东西的属性+方法,定义在一个对象中。

(2)继承:父对象中的属性+方法,子对象可以直接使用

(3)多态:同一个对象,在不同情况下,呈现不同的形态(注意:在js中无“多态”概念)

a、重载:同一方法名,传入参数不同,执行不同操作。

b、重写:子对象觉得父对象的成员不好用,可自己写一个,覆盖父对象成员。



4、继承——js中一切继承都是用原型对象实现“_proto_”

原型对象:每个函数对象都有一个原型对象

在构造函数的原型对象负责保存所有子对象共享的成员

建议:所有子对象共享的方法,都应定义在构造函数的原型对象中。

这样做,可避免重复定义方法的对象,浪费内存。

注意:所有内置类型的API都是定义在类型.prototype

//创建一个构造函数function Student(){    this.sname=sname;    this.age=age;}//在构造函数原型对象中定义公共方法Student.prototype.inteSelf=function(){    alert("I'm"+this.sname+"I'm"+age);}//用new关键字创建新对象var lilei=new Student("Li Lei",12);var hmm=new Student("Han Meimei",11);//在构造函数原型中定义公共属性Student.prototype.money=100;console.log(lilei.money);//先在当前对象本地去找,找不到再去原型  //原型也没有,才undefinedconsole.log(hmm.money);  Student.prototype.money-=20;console.log(lilei.money);

(1)扩展对象属性:2种

a、扩展共有属性:通过构造函数.prototype添加的属性

b、扩展自有属性:通过某一个具体子对象添加的属性

判断自有属性或共有属性:

a、判断自有属性:obj.hasOwnProperty("属性名")

b、判断共有属性:"属性名" in obj && !obj.hasOwnProperty("属性名")

(表示在原型关系中包含 且 子对象自己没有)



(2)原型链:由各级对象的_proto_逐级继承形成的关系

获得任意对象的父级原型对象:

Object.getPrototypeOf(子对象)  ==> 子对象._proto_


检测数组arr的_proto_原型链

var arr=[];

Object.getPrototypeOf(arr);

//[]

var arr=[];

Object.getPrototypeOf(arr)==Array.prototype

//true

Object.getPrototypeOf(Object.getPrototypeOf(arr))

//Object{}

2_1:检测对象的原型isPrototypeOf()

isPrototypeOf()用于判定一个prototype对象是否存在另一个对象的原型链中。如果是,返回true,否则返回false。


2_2:检查对象的父对象:

父对象.isPrototypeOf(子对象)


5、面向对象:封装、继承、多态

(1)创建对象:3种/4种

a、直接量:var obj={"属性名":值,

    "方法名":function(){

...this.属性名...

}

   }}_proto_——>Object.prototype


(2)new关键字:var obj = new Object();

obj.属性名=值;

obj.方法名=function(){

...this.属性名...

}


(3)使用构造函数反复创建相同结构的对象:2步

a、定义构造函数:

function 构造函数名(属性参数,...){

this.属性名=属性参数;

if(!构造函数名.prototype.方法名){

构造函数名.prototype.方法名=

    function(){

...this.属性名...

}

}

}

        b、使用new创建对象同时,调用构造函数:

var obj=new 构造函数名(属性值,...)


6、总结

(1)this:指代当前正在调用方法的对象

this和定义在哪无关!仅和调用时使用的对象有关

所有无关(不用var赋值的变量,匿名函数)都是window


(2)原型 原型链 继承

a、原型:保存所有子对象共有属性和方法的对象

所有函数都有prototype,指向自己的原型对象

所有对象都有_proto_,指向自己父级原型对象

(所有原型对象都有constructor,指向原型对应的构造函数)


b、原型链:所有父子级对象间_proto_形成的多级引用关系

——>多级继承


c、原型相关API:

1、判断自有属性和共有属性

a、判断自有——obj.hasOwnProperty("属性名")

b、判断原型链上的属性(2种)

判断不包含:if(!("属性名" in obj))——“用得最多”

    if(obj.属性名===undefined)

    if(!obj.属性名)

c、仅判断共有:必须满足两个条件

!obj.hasOwnProperty("属性名") 

        && 

obj.属性名

2、获得任意对象的原型

obj._proto_X

Object.getPrototypeOf(obj)


3、判断父对象是否在子对象的原型链上

父对象.isPrototypeOf(子对象)


d、检测一个对象是不是数组类型(4种)

1、Array.prototype.isPrototypeOf(obj)

2、obj instanceof Array

  对象  是不是   构造函数 的实例

3、obj.constructor==Array  仅判断直接父级

4、利用当前对象,强行调用原始的toString方法

Object.prototype.toString.call(obj) == "[Object Array]"

 .apply(obj)



e、继承

   为什么要继承?  ——代码重用、节省空间

1、直接继承对象:想方设法修改对象的_proto_

3种:

(1)仅修改一个对象的_proto_

Object.setPrototypeOf(子对象,父对象)

(2)通过修改构造函数的原型对象,实现批量修改后续子对象的继承关系

构造函数.prototype=父对象

强调:仅影响之后创建的对象的继承关系

之前创建的对象依然及继承旧构造函数.prototype


(3)Object.create(父对象[,{属性列表}]);

var hmm=Object.create(father);

var hmm=Object.create(father,

{intrSelf:{value:intrSelf},

 toString:{value}

}

);

该一句话可以办三件事:

a、创建一个空对象,

b、继承父对象的属性,

c、继承同时可再扩展属性和方法。


2、仅继承结构:

function 父类型构造函数(属性参数1,属性参数2){

this.属性1=属性参数1;

this.属性2=属性参数2;

}

function 子类型构造函数(属性参数1,属性参数2,属性参数3){

父类型构造函数.call(this,属性参数1,属性参数2);

this.属性3=属性参数3;

}

var obj=new 子类型构造函数(值1,值2,值3);




0 0