JS—属性相关

ECMAScript中有两种属性:数据属性与访问器属性。
[[]]表示内部值

  • 数据属性
  • [[Enumerable]]:表示能否通过for-in循环属性,默认值为true。
  • [[Value]]:包含这个属性的数据值,默认值为undefined。
  • 访问器属性
  • [[Enumerable]]:表示能否通过for-in循环属性,默认值为true。

我们之前见到的属性大部分都是数据属性。因为一般我们都可以直接访问这些属性的值。而不是在访问时,要调用get函数。


  • Object.defineProperty()
    这些属性的特性都是内部值,要想修改属性的特性,必须使用ECMAScript5的Object.defineProperty()方法。但是支持这个方法的浏览器有IE9+(IE8部分实现)、FireFox 4+、Safari 5+、Opera 12+和Chrome。

              var person={};
              //三个参数:属性所在对象、属性的名字、一个描述符对象
              Object.defineProperty(person,"name",{
                  writable:false,
                  value:"dudu"
              });
              alert(person.name);//dudu
              person.name="bobo";
              alert(person.name); //dudu
    

【注意】1、对于configurable这个特性一旦设置为false就没有办法在设置为true 2、再调用这个方法时,如果不指定特性的值,那么这些特性就默认为false啦,所以要是用了就指定。
var book={
_year:2004,
edition:1
};
Object.defineProperty(book,"year",{
get:function(){
return this._year;
},
set:function(newvalue){
if(newvalue>2004){
this._year=newvalue;
this.edition+=newvalue-2004;
}
}
});
book.year=2005;
alert(book.edition);
上述代码是用这个方法定义访问器属性。
_year前面的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。而访问器属性则包含一个getter函数和一个setter函数。
这两个函数并不是必须要写,如果不写则意味着该属性就是不能读不能写。

  • Object.defineProperties
    可以定义多个属性。
    var book={};
    Object.defineProperties(book,{
    year:{
    value:2004,
    writable:false
    },
    edition:{
    value:1,
    writable:false
    }
    });
  • Object.getOwnPropertyDescriptor
    读取属性的特性
    var descriptor=Object.getOwnPropertyDescriptor(book,"year");
    alert(descriptor.value);
    alert(descriptor.writable);//fasle
    以上三个方法,适用的浏览器版本是相同的。

上篇笔记说创建对象的方法,最终推荐的是封装的原型与构造函数混合的模式。我们在利用一个构造函数实例完一个对象后,其实可以再为他添加属性,可以不添加到原型内。

  •           function Person(){}
              Person.prototype.name="dudu";
              var person1=new Person();
              var person2=new Person();
              person1.name="xixi";
              alert(person1.name);//xixi
              alert(person2.name);//dudu
    

利用上面的代码来解释一下下面几个原理以及方法。

  • instanceof
    确定该实例是否属于该自定义类型
    alert(person1 instanceof Person);
  • isprototypeof()
    虽然所有实现中无法访问到[[prototype]],但可以通过isprototypeof()方法,来判断对象实例与原型对象之间的关系是否存在。
    alert(Person.prototype.isPrototypeOf(person1));//true
  • hasOwnProperty()
    alert(person1.hasOwnProperty("name"));//true
    alert(person2.hasOwnProperty("name"));//false
    这个属性时用来检测“name”属性是否属于person1这个实例对象的实例中。该函数在执行属性查找的时候,永远不会查找原型。
    关于上面的结果一个true一个false,是由原因的。
    每当代码读取某个对象的属性时,都会执行一次搜索,目标是具有给定名字的属性。
    搜索首先从对象实例本身开始,如果在实例中找到了具有给定名字的属性,则返回该属性的值,如果没有,则继续搜索该实例对象内指针指向的原型。
    所以person1.name="xixi";这句代码并不是覆盖了原型,而是在person1实例中添加了一个属性。
  • in
    alert("name" in person1)
    无论属性存在于实例中还是原型中,只要存在,就返回true。

枚举对象的属性

  • for-in
    在使用这个循环时,返回的是所有能够通过对象访问的,可枚举的属性。
    构造函数的属性,原型属性是不可枚举的。
    如果该属性是被重写的,那么默认该属性为可以枚举的,且这个属性也可以被for—in循环访问到。
    var obj={
    toString : function(){
    return "My Object";
    }
    };
    for (var prop in obj){
    if (prop=="toString"){
    alert("found toString");
    //IE8以前版本不显示,屏蔽了不可枚举的属性名
    }
    }
  • object.keys
    取得对象上所有可枚举属性
    function Person(name,age,job){
    this.name=name;
    this.age=age;
    this.job=job;
    this.friends=["bobo","xixi"];
    //
    if(typeof this.sayName!= "function")
    {
    Person.prototype.sayNmae=function(){
    alert(this.name);
    };
    }
    }
    var person=new Person("dudu",12,"painter")
    var keys=Object.keys(Person.prototype);//返回原型中的可枚举属性
    alert(keys);//sayName
    var keyss=Object.keys(person);//返回实例中的可枚举属性
    alert(keyss);//name、age、job、friends
  • Object.getOwnPropertyNames
    取得对象上所有属性,包括不可枚举的
    var keysss=Object.getOwnPropertyNames(Person.prototype);
    alert(keysss);//constructor、sayName
    var keyssss=Object.getOwnPropertyNames(person);
    alert(keyssss);//name、age、job、friends

你可能感兴趣的:(JS—属性相关)