对象相关的——————三个属性

先罗列下:

  prototype 原型

  class 类 

  extensible attribute  可扩展属性

 

prototype 属性:

  prototype 大概回顾下,从创建方式着手, 字面量创建的对象其原型为 Object.prototype,create() 创建的其原型指向第一个参数给定对象;  如果通过构造函数创建的其 指向 构造函数 prototype 属性指向的对象。

protptype 原型主要是用来继承属性以及方法。 那我们怎么来查找和设置原型对象尼?

  

  ECMAScript3中通过 o.constructor.prototype 来获取对象原型, 在后来ECMAScript5中新增了 Object.getPrototypeOf() 其基本语法如下:

  

   /**
      * Returns the prototype of an object.
      * @param o The object that references the prototype.
      */
    getPrototypeOf(o: any): any;

  

   通过不同方式创建,并获取其原型对象

//自面量
var custom = {
    name:"wangjing"
};
console.log(Object.getPrototypeOf(custom)); 

//构造函数
function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new  Person();
console.log(Object.getPrototypeOf(person1));

//create
var student = Object.create(person1);
console.log(Object.getPrototypeOf(student));


{}
Person { getName: [Function] }
Person { name: '文艺' }

 

   要想检测一个对象是否是另一个对象的原型 , 请使用 Object.prototype.isPrototypeOf() 先来看看基础语法

 /**
      * Determines whether an object exists in another object's prototype chain.
      * @param v Another object whose prototype chain is to be checked.
      */
    isPrototypeOf(v: Object): boolean;

   判断对象是否存在另一个对象的原型链上 ,存在返回 true 否则 返回 false 

//构造函数
function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new  Person();

Person.prototype.isPrototypeOf(person1) // true

 

 

class 属性:

 

  中文译为 “类”,在这里表示就是对象的类,是一个字符串,在ECMAScript3以及 ECMAScript5中都没有直接获取或设置的属性,只能间接的通过 Object.prototype.toString()方式获取。默认的toString()方法返回如下的格式

  [object class]

  为什么上面提到了默认的toString(),在大部分的情况下都覆盖了 Object.prototype.toString 方法,所以也只能通过 cell 方式进行调用;     

  

//构造函数
function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new  Person();

 function classOf(o){
     if(o === undefined || o === null) return;
     return Object.prototype.toString.call(o).slice(8,-1);
 }

console.log(classOf([]));// Array
console.log(classOf(new Date())); // Date
console.log(classOf(/\w/)); // RegExp
console.log(classOf(Person)); // Function
console.log(classOf(person1)); //Object
console.log(classOf(Window)); //Window

 

  从上面可以看出,通过内置对象构造函数(Array,Date)的生成的对象类属性返回值与构造函数名称相对应; 宿主对象也是一样, 通过自面量,create()创建的对象,其类名为 object, 自定义的对象,也返回 object; 所以通过class属性是没有办法区分对象的类  

 

可扩展性:

  可扩展属性决定是否可以往对象添加新的属性。 所有的内置对象和自定义对象都是显示可以扩展的。 宿主对象默认是可以扩展的,其可扩展也是由JavaScirpt引擎和ECMAScript5所规定的。

  如果想设置或查看对象可扩展性,ECMAScript5中提供两个方法 Object.isExtensible()、 Object.preventExtensions()。

 

  Object.isExtensible()  返回一个值,指示是否新的属性可以添加到一个对象

    

  /**
      * Returns a value that indicates whether new properties can be added to an object.
      * @param o Object to test.
      */
    isExtensible(o: any): boolean;

 

      Object.preventExtensions()  阻止添加属性到对象中

  

  /**
      * Prevents the addition of new properties to an object.
      * @param o Object to make non-extensible.
      */
    preventExtensions<T>(o: T): T;

  

 实例1:

function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new  Person();


console.log("before "+Object.isExtensible(person1)) //true

    Object.preventExtensions(person1);

console.log("after " + Object.isExtensible(person1))  // false

 虽然不可以添加 但是还是可以修改其自有属性的特性 configurable、enumerable、writable 但是其修改原则还是遵循 对象属性 讲述内容

   

function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new Person();

Object.preventExtensions(person1);
Object.defineProperty(person1,"name",{
    configurable:false   
});

console.log(Object.getOwnPropertyDescriptor(person1,
"name"));
  // { value: '文艺',writable: true,enumerable: true,configurable: false }

 

当configurable其属性为 ture时,属性可以被删除,

  

function Person(){
    this.name = "文艺";
}
Person.prototype.getName = function(){return name;}
var person1 = new Person();

Object.preventExtensions(person1);

delete person1.name   // true
console.log(person1.name); // undefined

 

   其只对影响对象本身的可扩展性;对其原型以及原型链上的对象不会有影响; 假如对象原型上添加某些属性时,在不可扩展对象也是可以访问到的

 

function Person(){
    this.name = "文艺";
}
var person1 = new Person();
Object.preventExtensions(person1);

console.log(person1.getName); // undefined

Person.prototype.getName = function(){return this.name;}

console.log(person1.getName()); // "文艺"

 

  与 preventExtensions 相似的一个方法 Object.seal() 先来了解了解

 

Object.seal()

  基本语法

  

    /**
      * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
      * @param o Object on which to lock the attributes.
      */
    seal<T>(o: T): T;

  这个方法 阻止对象扩展,并且把自有属性可配置属性设置为 false ,也就是说其属性不能被删除或配置, 但是其读写属性是可以修改的。

 

  既然有锁定方法,那么肯定与之对应的检测方法  Object.isSealed()

 /**
      * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.
      * @param o Object to test.
      */
    isSealed(o: any): boolean;

 

  实例一

  

function Person(){
    this.name = "文艺";
}
var person1 = new Person();

console.log(Object.getOwnPropertyDescriptor(person1,"name"));  // { value: '文艺',writable: true,enumerable: true,configurable: true }

Object.seal(person1);

Person.prototype.getName = function(){return this.name;}  // 正常添加

console.log(Object.getOwnPropertyDescriptor(person1,"name"));  // { value: '文艺',writable: true,enumerable: true,configurable: false }

delete person1.name  //TypeError: Cannot delete property 'name' of #<Person>

console.log(person1.getName()); // "文艺"

  与 preventExtensions 一样,只对影响对象扩展性,并不会影响其原型链上的对象。

 

 

Object.freeze() 将更严格的锁定对象 ------- 冻结

  freeze() 不仅锁定对象不能进行扩展,并且把自有属性设置不可配置以及设置为只读属性(如果是取值器属性并且其包含 seter 方法,那么还是可以正常对属性进行写操作);

    语法:

  

  /**
      * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.
      * @param o Object on which to lock the attributes.
      */
    freeze<T>(o: T): T;

 

  isFrozen() 用来检测对象是否被冻结了 
  

/**
* Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.
* @param o Object to test.
*/
isFrozen(o: any): boolean;

  

  实例:

  

    
function Person(){
  
this.name = "文艺"; } var person1 = new Person(); console.log(Object.getOwnPropertyDescriptor(person1,"name")); // { value: '文艺',writable: true,enumerable: true,configurable: true } Object.freeze(person1); console.log(Object.isFrozen(person1)); // true

Person.prototype.getName = function(){return this.name;} // 正常添加 console.log(Object.getOwnPropertyDescriptor(person1,"name")); // { value: '文艺',writable: false,enumerable: true,configurable: false }


//delete person1.name //TypeError: Cannot delete property 'name' of #<Person> //person1.name = "wj"; //TypeError: Cannot assign to read only property 'name' of object '#<Person>'

console.log(person1.getName()); // "文艺"

  与 preventExtensions 、seal 一样,只对影响对象扩展性,并不会影响其原型链上的对象。

 

可以利用 preventExtensions 、seal、freeze 三个方法来搭配使用,构建一个完全封闭的对象。

   var ooo = Object.seal(
        Object.create(
                Object.freeze({x:1}),
                {
                    y:{value:2,writable:true}
                }
            )
    );

    console.log(ooo); // {}
    console.log(ooo.x); // 1
    console.log(ooo.y); // 2  这里是不可枚举所以打印时 看到到

 

  

 

posted @ 2016-09-20 17:58  czhyuwj  阅读(585)  评论(0编辑  收藏  举报