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的屬性頁無法更改,這是其實是無法進行任何更改的.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM