js原型链接(二)和object类的create方法
原型链的内部执行方式
<script> function Myclass(){ this.x=" x in Myclass"; } var obj=new Myclass(); p(obj.x); p(obj.z); //undefined Myclass.prototype.z="z in Myclass"; p(obj.z); //首先查找自身属性,如果没有找到 将沿着原型链接 查找构造函数(Myclass)的prototype对象里找 </script>
属性的重写与删除与原型链无关
<script> function Myclass(){ this.x=" x in Myclass"; } Myclass.prototype.y="y in Myclass"; var obj=new Myclass(); p(obj.y);//y in Myclass obj.y="override y"; p(obj.y);//override y delete obj.y //true p(obj.y);//y in Myclass var obj2=new Myclass(); p(obj2.y);//y in Myclass obj.z='zzz'; p(obj.z);//zzz p(obj2.z);//undefined p(obj.prototype);//undefined </script>
获取原型对象的三种方法
<script> function Myclass(){} var proto=Myclass.prototype; var obj=new Myclass(); //通过第五版里加强 var proto=Object.getPrototypeOf(obj); //通过对象实例获得 var proto=obj.__proto__; //通过对象实例以及其构造函数 var proto=obj.constructor.prototype; p(obj.constructor==Myclass); //true </script>
通过constructor判定数据类型
<script> var d=new Date(); p(d.constructor);//function Date() { [native code] } var arr=[1,2,3]; p(arr.constructor);//function Array() { [native code] } var obj={}; p(obj.constructor);//function Object() { [native code] } </script>
constructor属性并不是对象的直接属性,而是通过原型链接 查找到的
每个对象在创建时 构造器会执行这样一句代码
this.prototype=
{
constructor:this,
__proto__:Object.prototype
}
通过改变prototype实现继承
<script> function Derived(){} //创建时 就有了Derived.prototype={constructor:Derived} p(Derived.prototype.__proto__==Object.prototype);//true p(Derived.__proto__);//function Empty() {} function Base(){} //原理同上 Derived.prototype=new Base(); //此时Derived.prototype的原型链接__proto__改变了指向 p(Derived.prototype.__proto__==Base.prototype); //true var obj=new Derived(); //此时 p(obj.__proto__==Derived.prototype);//true //现在obj里找 ,没有,到Derived.prototype引用的对象Base里找,没有,就到Base.prototype里找了 p(obj.constructor); //function Base(){} </script>
数据类型判定(instanceof与isPrototypeOf)
<script> var d=new Date(); p(Date.__proto__);////function Empty() {} p(d instanceof Date);//true p(d instanceof Object);//true p(Date instanceof Object);//true p(Object instanceof Date);//false function Derived(){} function Base(){} Derived.prototype=new Base(); var obj=new Derived(); p(obj instanceof Derived);//true p(obj instanceof Base); //true p(Derived instanceof Base);//false Derived不是由 Base构造函数生成的 p(Derived.constructor);//function Function() { [native code] } p(Derived instanceof Object);//true p(Derived.prototype.isPrototypeOf(obj)); //true Base.prototype.isPrototypeOf(obj);//true Object.prototype.isPrototypeOf(obj)//true </script>
属性的枚举
in 可以可判断本身属性和通过继承来的属性 是否存在于某个对象
hasOwnProperty只列出本身可以枚举的属性
有些属性被枚举出来是因为enumerable属性为false
getOwnPropertyNames可以无视枚举属性,列举出所有属性
<script> var obj={x:1,y:2}; p(Object.keys(obj));//x,y obj.z=3; //obj.prototype.p='pp';//实例 prototype属性 p(obj.prototype);//undefined p(obj.__proto__==Object.prototype); //true p(Object.keys(obj));//x,y,x var arr=[1,2,3]; p(Object.keys(arr)); //0,1,2 p(Object.getOwnPropertyNames(arr)); //0,1,2,length p(Object.keys(Object.prototype));//空 p(Object.getOwnPropertyNames(Object.prototype)); /* constructor,toString,toLocaleString,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,__defineGetter__,__lookupGetter__,__defineSetter__,__lookupSetter__,__proto__ */ //对于enumerable可根据propertyIsEnumerable来判断 function Myclass(){ this.x=1;this.y=2; } Myclass.prototype.z=3; var obj=new Myclass(); p(Object.getOwnPropertyNames(obj)); //x,y 不列举通过继承获取的属性 p(Object.keys(obj));// x,y for(var key in obj){ p(key); } //x,y,z </script>
ECMAScript里的Object类
Object里的create方法,是除了对象字面量与new表达式之外的第三种官方的生成对象的方法
第一个参数需要一个原型对象,第二个参数需要一个属性对象。
如果将一个null作为原型传递给create方法 ,则会生成一个没有进行原型继承的对象
<script> var obj=Object.create(null); p(Object.getPrototypeOf(obj));//null p("toString" in obj);//false var obj=Object.create(Object.prototype); //与 var obj={}; //等效 p(obj.__proto__===Object.prototype);//true p(obj.constructor==Object);//true function Myclass(){} var Proto={x:2,y:3}; Myclass.prototype=Proto; var obj=new Myclass(); //下面代码等价 var Proto={x:2,y:3}; var obj=Object.create(Proto); </script>
属性对象
create方法的第二个参数是一个关联数组,其键为属性名,其值为属性描述符(属性对象)
属性描述符指由下表中的 由属性组成的关联数组
属性对象
create方法的第二个参数是一个关联数组,其键为属性名,其值为属性描述符(属性对象)
属性描述符指由下表中的 由属性组成的关联数组
属性的属性名 |
含义 |
writable |
可以改写属性的值 |
enumerable |
可以通过for in枚举出 |
configurable |
可以改变属性的属性,可以删除属性 |
get |
可以指定属性值的getter函数 |
set |
可以指定属性值的setter函数 |
属性值通过value属性指定.大部分属性的默认值是false,也可以显示地指定为true
<script> var obj={x:2,y:3}; //与下面代码 var obj=Object.create(Object.prototype, { x:{value:2,writable:true,enumerable:true,configurable:true}, y:{value:2,writable:true,enumerable:true,configurable:true} } ); // 是等效的 </script>
与Object类的属性的属性有关的方法
方法 |
说明 |
defineProperty(o,p,attributes) |
向对象o增加/更新具有特定信息的属性p |
defineProperties(o,properties) |
向对象o增加/更新具有特定信息的属性 |
getOwnPropertyDescriptior(o,p) |
返回对象o的直接属性p的信息(值与属性) |
<script> var obj=Object.create(Object.prototype,{x:{value:2}}); //除了显式指定的属性,其它的值都为false value默认为undefined Object.getOwnPropertyDescriptor(obj,'x'); //{value:2,writable:false,enumerable:false,configurable:false} //新增属性y Object.defineProperty(obj,'y',{value:3,enumerable:true}); Object.getOwnPropertyDescriptor(obj,'y'); //{value:3,writable:false,enumerable:true,configurable:false} // 新增属性z Object.defineProperties(obj, { z:{value:function(){alert('z called');},enumerable:true} } ); Object.getOwnPropertyDescriptor(obj,'z'); //{value:function(){alert('z called');},enumerable:true,configurable:false,writable:false} </script>
如果属性的configurable属性为true,可以更改包括值在内的所有属性,反之如果为false,则不能
由于此时configurable的属性页无法更改,这是其实是无法进行任何更改的.