Javascript学习笔记1 理解对象 属性 原型对象

属性类型

对象属性包括两种类型:数据属性访问器属性

数据属性
包含一个数据值的位置,在这个位置可以读取和写入值。其包括4个特性:configurable(能否删除或修改,默认为true),enumerable(能否通过for-in语句返回属性,默认为true),writeable(能否修改属性的值,默认为true),value(属性值,默认为undefined)

var person = {
    name: "zjw"
};

访问器属性
不包含数据值,其包含一对儿gettersetter函数,用于读取和写入访问器属性。其包括4个特性:configurable(能否删除或修改),enumerable(能否通过for-in语句返回属性),get(读取属性时调用的函数,默认为undefined),set(写入属性时调用的函数,默认为undefiend)。在属性前面加上下划线(_)用于表示只能通过对象方法访问的属性。

var book = {
    _year: 2004,
    edition: 1
};

Object.defineProperty()
无论数据属性或是访问器属性,均可以用该方法定义或修改属性特性。该方法接受3个参数:属性所在的对象,属性名称字符串和描述符对象
对数据属性修改特性

var person = {};
Object.defineProperty(person,"name",{
    writeable: false,
    value: "zjw"
});

定义访问器属性特性

Object.defineProperty(book,"year",{
    get: function(){
        return this._year;
    },
    setfunction(newValue){
        this._year = newValue;
        this.edition += newValue - 2004;
    }
});

book.year = 2005;
alert(book.edition); //2

Object.getOwnPropertyDescriptor()
使用该方法,取得给定属性的描述符,接受两个参数:属性所在的对象和要读取其描述符的属性名称

var descriptor = Object.getOwnPropertyDescriptor(book,"year");
alert(descriptor.configurable); //false

创建对象

工厂模式

function createPersonnameagejob){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job
    o.sayname = function(){
        alert(this.name)
    };
    return o;
}

var person = createPerson('zjw',29,"student");
  • 不足没有解决对象识别问题。无法得知对象的类型

构造函数模式

function Personnameagejob){
    this.name = name;
    this.age = age;
    this.job = job
    this.sayname = function(){
        alert(this.name)
    };
}

var person = new Person('zjw',29,"student");
  • 没有显式的创建对象,而是直接把属性和方法赋予给了this对象
  • 没有return语句
  • 要创建实例,必须使用new操作符,表明其是构造函数(如果不使用,则与普通函数没什么两样)
//在另一个对象的作用域中调用
var o = new Object();
Person.call(o,'zjw',29,"student");  //调用Person函数,不使用new操作符
o。sayname();   //"zjw"
  • 不足每次创建对象实例时,其方法都要重新创建一次

原型模式
每个函数都有个prototype属性,其是一个指针,指向一个对象,这个对象的用途是可以包含某种类型对象所有实例共享的属性和方法

function Person(){
    Person.prototype.name = "zjw";
    Person.prototype.age = 29;
    Person.prototype.job = "student"
    Person.prototype.sayname = function(){
        alert(this.name)
    };
}

var person1 = new Person();
person.sayname();  //"zjw"
var person2 = new Person();
alert(person1.sayname == person2.sayname); //true

每个构造函数都有个prototype属性,该属性指向原型对象而原型对象的constructor属性则指向构造函数

可以使用isPrototypeOf()确定原型对象的关系

Person.prototype.isPrototypeOf(person1) //true

可以使用Object.getPrototypeOf()获取某个对象的原型对象

prototype = Object.getPrototypeOf(person1);
alert(prototype.name); //"zjw"
  • 虽然可以通过实例访问到原型对象,但不能通过实例重写原型中的值
  • 当实例新添加的属性与原型对象的属性同名时会覆盖原型对象的属性
  • 某些浏览器可以使用对象的__proto__属性访问到原型对象

使用delete可以删除实例的属性

delete person1.name

使用hasOwnProperty()方法可以检测属性存在于原型对象,还是实例

person1.hasOwnProperty("name")
  • hasOwnProperty()只对实例的属性返回true

无论属性存在于对象实例还是原型对象中只要存在in操作符就返回true

name in person1 //true
  • 使用for-in循坏时,返回的是所有能通过对象访问的,可枚举的(enumerated)的属性,无论存在于对象还是原型

重写原型对象

Person.prototype = {
    constructor:Person,    //重写原型对象时,会丢失constructor属性,需要将其重新指向构造函数
    name:"zjw",
    age:29,
    sayName:function(){
        alert(this.name);
    }
}

原型具有动态性,对原型对象所做的任何修改(重写原型是个例外)都能够立刻从实例上反映出来

var friend = new Person();
Person.prototype.sayHi = function(){
    alert("hi");
};
friend.sayHi();  //"hi"
  • 但当重写原型时,将会切断现有原型与实例之间的联系

所有原生引用类型(Object、Array、String等)都是在其构造函数的原型上定义的方法,但原型模式也有不足,当原型对象中具有引用型属性时,通过某个实例修改该属性,会导致所有实例的该属性发生变化(因为该属性是引用类型,所有实例的该属性都指向同一个)。因此创建自定义模式最常见的方式就是构造函数和原型模式结合

function Personnameagejob){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friend = ["zjw","wxx"];
}

Person.prototype = {
    constructor:Person,
    sayName:function(){
            alert(this.name);
        }
};
  • 使用构造函数定义实例属性,使用原型定义共享属性和方法

动态原型模式
将构造函数和原型封装到构造函数中,而不是独立定义

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friend = ["zjw","wxx"];
    if (typeof this.sayName != "function"){  //判定原型是否已经初始化,保证只初始化一次原型
        Person.prototype.sayName = function(){
            alert(this.name);
        }
    }
}
  • 该种模式不能使用对象字面量重写原型,因为会切断原型和实例的联系

除此之外,还有寄生构造函数模式(工厂模式+new操作符)0和稳妥构造函数(不使用this和new),他们不依赖于原型对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值