对象

    1 对象类型定义

    2 对象实例

    3 对象表示方式(对象字面量)

    4 对象属性和方法,及属性特性

    5. 原型与原型链

    6. 面向对象设计编程

 


1 对象类型定义:无序属性的集合,其属性可以包含简单数据类型值,函数或者对象。

 

2 对象实例:(对象类型的值) 每种数据类型都有相应的值,比如数字8是Number类型的一个值。对于对象类型,值被称为对象实例,任意一种对象都是object对象类型的实例(值)。比如简单类型包装对象(boolean,string,number)就是对象类型的值(实例)。

 

3 对象的表示方式:(对象字面量) 最外层的一对大括号({})就表示这是一个对象字面量。数组类型的实例也可以直接通过数组字面量来表示。

//对象字面量和数组字面量
//流行的JSON数据格式就是基于如此,不过两者有区别,

{    //对象字面量
    name: 'Games',
    getName:fucntion(){
        return this.name;
    }
}

[{    //数组字面量    
    name: 'Games',
    age:'31'
},{    
    name: 'Kobe',
    age:'34'
}

]

3.1 对象字面量直接创建对象

var person = {
    "name":"Games",
    "age":"31"
}; 

//用对象字面量创建对象,实际没有利用构造函数
//但创建出的对象仍然有指向这个函数的属性
//constructor用于保存创建这个对象实例的函数

console.info(person.constructor===Object);//true

 

4. 对象属性和方法,及属性特性

     方法本质也是一种属性,只是属性的值类型是函数,就称为方法。

     1_属性类型:

                     数据属性:直接属性值的属性

                     访问器属性:通过getter/setter方法来访问属性值的属性

                     内部属性:不能通过代码直接访问的属性,只是为了规范说明目的而存在

    2_常见内部属性 (在规范中也使用两个中括号的形式来描述)

哪些对象具备 内部属性名称 说明
所有对象 [[Put]] 属性赋值调用的方法
所有对象 [[Get]] 读取一个属性值调用的方法
所有对象 [[Prototype]] 指向每一个对象的原型对象,不能在代码中直接访问这个内部属性,
可以通过Object.getPrototypeOf(object)来获取原型对象(在Firefox中可以通过__proto__来直接访问)。
所有对象 [[Class]] Object.prototype.toString方法中按照规范内建对象会返回包含[[Class]]的值“[object class]”,
而内建对象的[[Class]]值就是相应的名称(比如Array对象的[[Class]]值为'Array'),
因此可以通过Object.prototype.toString.call(value) == '[object Array]'来判断value是否是一个Array。
New创建对象 [[Construct]] 使用new操作符调用一个函数时,后台调用[[Construct]]
调用call方法 [[Call]] 而使用call方法来调用函数时,后台会调用[[Call]]
执行函数时 [[Scope]]

当一个函数被执行时,就会创建一个[[Scope]]对象,可以理解为[[Scope]]就是函数活动对象,而this、arguments、形参、函数内部定义的变量和函数都是的[[Scope]]对象的属性。

 

    3_属性定义及定义属性相关特性(用来描述属性的特性)

最常见的定义属性的方法就是直接在对象上添加属性,比如obj.name = 'linjisong',这种情况下定义的属性所具有的内部特性都是默认的。

如果想定义一个值不能被修改的属性要怎么做呢?

       属性定义方法:defineProperty() 定义一个属性 和 defineProperties() 定义一组属性

       属特相关特性:

特性含义 特性名称 直接添加属性时默认值 通过方法定义属性时默认值
属性具体的值 value undefined undefined
能够修改属性值

writable

true   可以

false  不可以
能否通过for-in枚举返回属性 enumerable true   可以 false  不可以
能够重新配置属性特性或删除属性 configurable true   可以 false  不可以
读取属性时调用的函数 get undefined undefined
写入属性时调用的函数 set undefined undefined
//注意说明

//       1. 对于访问器属性,[[Get]]、[[Set]]不一定都有,没有[[Get]]的属性不能读(返回undefined,严格模式下抛出异常),没有[[Set]]的属性不能写(会忽略,严格模式下抛出异常)

//       2.  使用属性定义方法时 [[Enumerable]] [[Configurable]] [[Writable]] 默认值为false。

//       3.  这些方法设置或获取的属性特殊和属性的类型有关,比如数据属性只能设置[[Confirurable]]、[[Enumerable]]、[[Writable]]、[[Value]]。

定义属性:

// 创建一个包含一个默认属性job的对象(job属性可以修改、删除、在for-in中枚举)
var person = {job:'it'};

Object.defineProperty(person, 'name', {            // 添加一个不能被修改、删除的name属性                  

    value:'Games',                                         
    enumerable:true                                         //可以通过for-in遍历,但是Configurable,Writable都为false.所以不能被修改和删除
});


Object.defineProperties(person, {                            // 定义多个属性(数据属性year和访问器属性age)
    year:{                                                   //数据属性year可以直接被访问
        value : 2012, 
        configurable:true,
        writable:true    
    },
    age:{                                                    //访问器属性age
        get : function(){
            return this.year-1984;
        }
    }
});

var job = Object.getOwnPropertyDescriptor(person, 'job');
console.info(job.configurable);                             //true,直接添加属性时默认为true

var name = Object.getOwnPropertyDescriptor(person, 'name');
console.info(name.configurable);                            //false,使用属性定义方法添加属性时默认为false
console.info(person.name);                                  //Games
person.name = 'Kobe';                                      //由于不能修改,所以值不会改变,在严格模式下会抛出异常
console.info(person.name);                                 //Games

person.year = 2015;
console.info(person.year);                                //2015
console.info(person.age);                                  //31,在修改year的同时,也修改了age属性

对象常用属性和方法:

类型

名称

说明

属性

constructor

指向用于创建当前对象的构造函数

方法

hasOwnProperty(propertyName)

检查给定的属性是否在当前对象实例中

propertyIsEnumerable(propertyName)

检查给定的属性是否能够是使用for-in语句来枚举

isPrototype(object) 检查传入的对象是否是另一个对象的原型
toLocalString() 返回对象的字符串表示,该字符串与执行环境的地区相对应
toString() 返回对象的字符串表示
valueOf() 返回对象的字符串、数值或布尔值表示,通常与toString()方法返回值相同
 

create(prototype[,descriptors])

创建一个具有指定原型且可选择性地包含指定属性的对象

 

getOwnPropertyNames(object)

返回对象的属性(方法)的名称

 

getPrototypeOf(object)

返回对象的原型

keys(object)

返回对象的可枚举属性(方法)的名称

       对象属性和方法访问方式:

       确定值:用.点号方式访问,如:person1.name;

       不确定值:使用方括号[],如: oDiv[this.index];   方括号内部可以是一个变量或者表达式。

 

如何遍历对象实例自身的属性而不包括从原型链继承而来的属性。

for(var propertyName in object){                    //如果for-in循环
  if(object.hasOwnPorperty(propertyName)){        //通过方法判断是否属于自身对象的属性
    //循环处理
  }
}

 

5. 原型与原型链

1.  原型与原型链

     每个对象都有一个原型对象,而原型对象本身也是一个对象,也有自己的原型对象,这样就形成了一个圆形链直至null对象。

     对象的内部属性[[Prototype]]指向的就是对象的原型对象,而Object.prototype的原型对象为null。

 

2. 原型链作用-属性方法查找-继承

     在访问一个对象的属性(方法)时,JS引擎会先查找对象本身有没有这个属性,如果有,返回这个属性值,如果没有,则查找对象的原型是否有这个属性,有则返回,如果没有就继续查找原型对象的原型直至最后一个原型对象。

 

3. 对象的原型(__proto__), 构造函数的原型(prototype)

    每一个构造函数都有一个属性prototype,这个属性是在函数定义过程中添加的,它指向的对象就是所有使用该函数创建的实例对象原型对象

    构造函数的原型对象有一个属性constructor指向该构造函数。

   1.所有函数(构造器)的__proto__都指向Function.prototype.

   2.所有对象的原型(__proto__)都指向其构造器的prototype.

 

181637013624694

4. 原型链与作用域链区别

  属性查找是沿着原型链,标识符查找是沿着作用域链,都是一个逐级查找的过程。

 

6. 面向对象设计编程

1. JS中没有类(class),但是利用构造函数及其原型对象来替代,

2. 类和对象的区别于关系

    类是抽象的,代表一类事物;对象是具体的,代表一个实际的事物;类是对象实例的模板,对象实例是类的一个个体。

3. 抽象

    在定义一个类时,实际上就是把一类事物的共有属性和行为提取出来,形成一个模板。

4. 面向对象三大特征

    封装:封装就是把抽象出来的属性和对属性的操作方法封装在一起,属性被保护在内部,程序的其它部分只有通过被授权的操作(函数),才能对属性进行操作,比如公开的登录方法,验证通过则可以查看私有的属性,比如账户余额等!

    继承:实例化对象可以继承其对应类的属性和方法,类也可以继承其它类的属性和方法,代码复用,提高效率

    多态:即多种状态,就是指一个引用在不同情况下的多种状态,通过指向父类的引用,来调用不同子类中实现的方法。JS中一个变量的类型是在运行过程中由JS引擎决定的。JS不支持重载,子类可以覆盖父类的方法,达到不同状态实现不同的功能需求。

 

定义类及实例化对象方法: 用构造函数方式来定义对象特有属性,用原型方式来定义类共有的属性和方法。

子类继承父类的方法:  用构造函数方式实现对父类属性的继承,用原型方式实现对原型属性和方法的继承。

//定义一个父类
    function Person(name,sex){               //用构造函数方式来定义对象特有属性
    this.name = name;
    this.sex = sex;    
    }

    Person.prototype.sayHello = function(){   //用原型方式来定义类共有的属性和方法。
        return "Hello!";    
    };


    //定义一个子类
    function Student(name,sex,major){         //用构造函数方式来继承父类的属性    
        Person.call(this,name,sex,major);      //创建子类实例时,第二次调用父类构造函数,并利用call改变this指向
        this.major = major;
    }

    Student.prototype = new Person();         //通过原型继承方式,子类的原型对象指向父类的实例,可以继承父类原型方法
    Student.prototype.study = function(){     //子类的方法
        return "Never too late to learn!";    
    }

    var s1 = new Student('Games','male','IT');   //实例化子类的对象,并初始化
    
    console.info(s1.name);                         //Games  继承父类的属性
    console.info(s1.sex);                          //male   继承父类的属性
    console.info(s1.sayHello());                   //Hello  继承父类的方法
    console.info(s1.major);                        //IT     子类自身的属性
    console.info(s1.study());                      //Never too late to learn!  子类自身的方法
 
寄生组合式继承:这种方式只调用了一次父类构造函数,从而避免了在子类型的原型对象上创建不必要的属性,也能够保证原型链不变,可以正常使用instanceof和isPrototypeOf()。
function create(o){                          //创建一个新对象并返回
    var fn = function(){};
    fn.prototype = o;
    return new fn();    
}

function inherit(sub, sup){               //实现子类原型继承父类原型实例
    var prototype = create(sup.prototype);
    prototype.constructor = sub;
    sub.prototype = prototype;    
}


//定义一个父类
    function Person(name,sex){               //用构造函数方式来定义对象特有属性
    this.name = name;
    this.sex = sex;    
    }

    Person.prototype.sayHello = function(){   //用原型方式来定义类共有的属性和方法。
        return "Hello!";    
    };


    //定义一个子类
    function Student(name,sex,major){         //用构造函数方式来继承父类的属性    
        Person.call(this,name,sex,major);      //创建子类实例时,第二次调用父类构造函数,并利用call改变this指向
        this.major = major;
    }

    inherit (Student,Person);                 //通过inherit方法继承
    Student.prototype.study = function(){     //子类的方法
        return "Never too late to learn!";    
    }

    var s1 = new Student('Games','male','IT');   //实例化子类的对象,并初始化
    
    console.info(s1.name);                         //Games  继承父类的属性
    console.info(s1.sex);                          //male   继承父类的属性
    console.info(s1.sayHello());                   //Hello  继承父类的方法
    console.info(s1.major);                        //IT     子类自身的属性
    console.info(s1.study());                      //Never too late to learn!  子类自身的方法
 
 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2015-08-09 20:40  331415706  阅读(309)  评论(0编辑  收藏  举报