对象相关的——————三个属性
先罗列下:
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"));
当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 这里是不可枚举所以打印时 看到到