js中對(duì)象的分類
對(duì)象的分類:
1.內(nèi)置對(duì)象:由ECMA實(shí)現(xiàn) 的,不依賴于宿主環(huán)境的對(duì)象,這些對(duì)象在js程序執(zhí)行之前就已經(jīng)存在了。
本地對(duì)象:Object,Array,String,Number,Boolean,Date等。
單體內(nèi)置對(duì)象:只有兩個(gè)Global,Math。與本地對(duì)象的區(qū)別在于:不需要加new 。
2.宿主對(duì)象:就是js寄宿環(huán)境定義的對(duì)象。
在瀏覽器端的js而言,宿主對(duì)象就是瀏覽器對(duì)象。例如:window,document,history等。
Global對(duì)象:定義的全局變量,全局函數(shù),其實(shí)就是這個(gè)對(duì)象的屬性。
其它的本地對(duì)象其實(shí)也是它的屬性。從這個(gè)意義上講,Global東西相當(dāng)于是js程序運(yùn)行總管。
3.自定義的對(duì)象
window對(duì)象
window是Global對(duì)象在瀏覽器端的代言人。換句話說,在瀏覽器端編寫js程序,就直接可以使用window來代替global。(如果你在你服務(wù)器端,在node.js中g(shù)lobal對(duì)象是真實(shí)存在的)。
定義的任何全局變量,函數(shù),都是window對(duì)象的屬性。
var a = 1,
b = 2;
console.log(window.a) //1
console.log(window.b) //2
但是在使用中window可以省略。
js的三條定律
一切都是對(duì)象
1.基本數(shù)據(jù)類型也當(dāng)作對(duì)象處理
var string = 'dabao';
console.log(string.length);
string為基本數(shù)據(jù)類型,但是他同樣有方法,在運(yùn)行過程中js會(huì)把它臨時(shí)轉(zhuǎn)變成一個(gè)包裝類的對(duì)象。
var string = new String('dabao')
2.引用類型的數(shù)據(jù)也是對(duì)象
函數(shù):
function f(){}
console.log(f);
console.log(f instanceof Object) //true

數(shù)組:
給數(shù)組添加新屬性,一定要按下標(biāo)的序號(hào)規(guī)則去加,如果下標(biāo)是字符串(正確的下標(biāo)應(yīng)該是數(shù)字),則length的值不會(huì)增加,但,添加的屬性確定是添加成功。
var a = [1,2,3];
a.name = 'dabao';
a[3] = 'xiaobao';

對(duì)象自然也是對(duì)象。
屬性操作
四個(gè)特征:
configurable:是否可以刪除。默認(rèn)為true。
writable:是否可以修改屬性的值。默認(rèn)為true。
enumerable:是否可以枚舉。是否可以通過for in 循環(huán)來輸出。默認(rèn)為true。
Value:值。默認(rèn)為undefined。
Object.defineProperty(對(duì)象名,“屬性名”,{
Configurable:
Writable:
Enumerable:
Value:
})
var obj = {}
Object.defineProperty(obj,"name",{
configurable:false,
writable:false,
value:'dabao'
})
console.log(obj)
obj.name = 'xiaobao';
console.log(obj.name)
delete obj.name;
console.log(obj);

函數(shù)被調(diào)用次數(shù)的例子
function f(){
f.counter++;
}
f.counter = 0;
f();
f();
f();
console.log(f.counter) //3
深入理解var 與不加var 的區(qū)別
a = 1;
console.log(a); //1
var b = 2;
console.log(b); //2
delete a;
delete b;
console.log(window.a); //undefined
console.log(window.b); //2
遺漏聲明變量就是window對(duì)象的屬性,是可以被刪除的。而加var聲明是不可刪除的。為什么呢?因?yàn)槭褂胿ar添加的屬性有一個(gè)特性是:configurable:true;
對(duì)象是由函數(shù)創(chuàng)造
var array = new Array(1,1)
var f = new Function('x','y','return x+y');
var n = new Number(1)
var obj = new Object();
無論是數(shù)組還是函數(shù)還是基本數(shù)據(jù)類型都是由函數(shù)創(chuàng)建的。
原型與原型鏈
prototype就是原型,__ proto__ 稱為隱式原型。前后有兩個(gè)下劃線。它對(duì)外是隱藏的,我們在程序開發(fā)過程,不會(huì)直接使用它。
1.函數(shù)都有一個(gè)prototype屬性
每個(gè)函數(shù),都會(huì)有很多屬性(因?yàn)楹瘮?shù)也是對(duì)象,而對(duì)象是屬性的集合),其中一定有一個(gè)prototype屬性。
函數(shù)的prototype屬性是一個(gè)對(duì)象,這個(gè)對(duì)象中有很多方法。但是一定有一個(gè)方法:constructor,constructor指向 這個(gè)函數(shù)本身。
(在es6的語法中,使用class創(chuàng)建類,實(shí)際上每個(gè)類都有一個(gè)constructor,即使你不設(shè)置,也會(huì)默認(rèn)存在)
2.每一個(gè)對(duì)象都有一個(gè)__ proto__屬性
對(duì)于函數(shù)而言,也是對(duì)象,所以函數(shù)都會(huì)有一個(gè)prototype和一個(gè)__ proto__屬性。
對(duì)象的__ proto__屬性指向創(chuàng)建這個(gè)對(duì)象的函數(shù)的prototype。
function F(){
this.name = 'dabao'
}
var f = new F();
console.log(F.prototype)
console.log(f.__ proto__)

如果訪問一個(gè)對(duì)象的屬性時(shí),先在這個(gè)對(duì)象自己的屬性中去找,如果找不到,則沿著__ proto__這個(gè)屬性找,如果__ proto__這個(gè)對(duì)象中還是沒有找到,就在__ proto__對(duì)象的__ proto__屬性中去找,依次下去,這就是原型鏈。
也就是說,當(dāng)我們訪問對(duì)象,會(huì)尋找自己的屬性,當(dāng)找不到自己的屬性時(shí),就去找自己的隱式原型__ proto__,__ proto__指向創(chuàng)建該對(duì)象方法的prototype,prototype實(shí)際上也是一個(gè)對(duì)象,它也有一個(gè)__ proto__這樣會(huì)繼續(xù)往上一級(jí)找。
由于對(duì)象的__ proto__[隱式原型]與創(chuàng)建這個(gè)對(duì)象的函數(shù)(構(gòu)造器)的prototype是一致的。
所以理論上,你對(duì)__ proto__修改會(huì)直接影響prototype。
建議你只使用prototype[原型]
創(chuàng)建對(duì)象
字面量方法
var obj = {
name : 'dabao',
say : function(){
console.log(this.name)
}
}
工廠模式
function creatObj(){
var obj = {}
obj.name = 'dabao';
obj.say = function(){
console.log(this.name)
}
return obj;
}
構(gòu)造器模式
function F(){
this.name = 'dabao'
}
var f = new F()
到底做了什么? 為什么給一個(gè)函數(shù)加一個(gè)new 就能產(chǎn)生對(duì)象呢?
new一共做了如下四件事:
1.創(chuàng)建一個(gè)對(duì)象 var obj = {}
2.F.call(obj);先執(zhí)行F()函數(shù),同時(shí)把this用obj來代替。把F()構(gòu)造器設(shè)置的各種屬性值,直接賦給o.
3.obj.__ proto__ = F.prototype
4.返回 obj;
原型模式
function F(){
this.name = 'cxh'
}
F.prototpe.say = function(){}
將方法寫在原型上。
注意:不要去修改對(duì)象的__ proto__。會(huì)導(dǎo)致由構(gòu)造器所產(chǎn)生的全部的對(duì)象的屬性都會(huì)受到影響。
覆蓋prototype的問題:
因?yàn)閜rototype里面肯定有一個(gè)contructor方法,假如采用直接覆蓋的方法,將把當(dāng)前的對(duì)象的構(gòu)造器歸置為object。
我們可以采用jq的方法

重新設(shè)置 constructor。
繼承
js特點(diǎn):生來繼承
Var s ={};
s.toString();//為什么有toString()?從__ proto__獲取的。
1.原型繼承
function Parent(){}
function Son(){}
Son.prototype = Parent.prototype
Son.prototype.constructor = Son
2.類式繼承
function Parent(name){
this.name = name
}
function Son(name,newName){
this.newName = newName;
Parent.call(this,name)
}
針對(duì)屬性使用 類式繼承
針對(duì)方法是用原型繼承
使用es6 extends繼承。
繼承方式可以有很多種,但是無論哪種,都是
子類屬性即父類的屬性
子類的方法繼承父類的方法
即
son.__ proto__ = parent
son.prototype.__ proto__ = parent.prot0type