作用域
我們知道,Javascript的變量采用鏈?zhǔn)阶饔糜颉Wx取變量的時候养筒,先在當(dāng)前作用域?qū)ふ以撟兞吭罚绻也坏剑颓巴弦粚拥淖饔糜驅(qū)ふ以撟兞吭畏唷_@樣的設(shè)計挤悉,使得讀取局部變量比讀取全局變量快得多。
讀取全局變量:
var a = 0;
function x(){
a += 1;
}
讀取局部變量:
function y(){
var a = 0;
a += 1;
}
第二段代碼讀取變量a的時候兵多,不用前往上一層作用域尖啡,所以要比第一段代碼快五六倍。
prototype模式:
var X = function(name){ this.name = name; }
X.prototype.get_name = function() { return this.name; };
closure模式:
var Y = function(name) {
var y = { name: name };
return { 'get_name': function() { return y.name; } };
};
同樣是get_name()方法剩膘,closure模式更快衅斩。
iframe嵌套
"window.location.href"、"location.href"是本頁面跳轉(zhuǎn)
"parent.location.href"是上一層頁面跳轉(zhuǎn)
"top.location.href"是最外層的頁面跳轉(zhuǎn)
舉例說明:
如果A,B,C,D頁面怠褐,引入iframe進(jìn)行頁面嵌套畏梆,
D是C的iframe,C是B的iframe奈懒,B是A的iframe奠涌,
如果D中js這樣寫
"window.location.href"、"location.href":D頁面跳轉(zhuǎn)
"parent.location.href":C頁面跳轉(zhuǎn)
"top.location.href":A頁面跳轉(zhuǎn)
現(xiàn)在終于明白了連接的時候target的用法了:
_blank:重新打開一個窗口
_parent:父窗口執(zhí)行重定向
_self:自身頁面重定向
_top:第一個父窗口重定向
綜上所述可知:parent.window:父窗口對象 top.window:第一個父窗口的對象磷杏。
對象
對象屬性描述符的類型分為兩種:數(shù)據(jù)屬性和訪問器屬性溜畅。
數(shù)據(jù)屬性包含一個數(shù)據(jù)值的位置,在這個位置可以讀取和寫入值极祸。數(shù)據(jù)屬性有4個特性慈格。
1、configurable
(可配置性)
可配置性決定是否可以使用delete刪除屬性遥金,以及是否可以修改屬性描述符的特性浴捆,默認(rèn)值為true。
2稿械、enumerable
(可枚舉性)
可枚舉性決定屬性是否出現(xiàn)在對象的屬性枚舉中选泻,比如是否可以通過for-in循環(huán)返回該屬性,默認(rèn)值為true美莫。
3页眯、writable
(可寫性)
可寫性決定是否可以修改屬性的值,默認(rèn)值為true厢呵。
4餐茵、value
屬性值)
屬性值包含這個屬性的數(shù)據(jù)值,讀取屬性值的時候述吸,從這個位置讀忿族;寫入屬性值的時候锣笨,把新值保存在這個位置。默認(rèn)值為undefined道批。
對象屬性是名字错英、值和一組屬性描述符構(gòu)成的。而屬性值可以用一個或兩個方法替代隆豹,這兩個方法就是getter和setter椭岩。而這種屬性類型叫訪問器屬性。
1璃赡、getter
在讀取屬性時調(diào)用的函數(shù)判哥。默認(rèn)值為undefined。
2碉考、setter
在寫入屬性時調(diào)用的函數(shù)塌计。默認(rèn)值為undefined。
和數(shù)據(jù)屬性不同侯谁,訪問器屬性不具有可寫性(writable)锌仅。如果屬性同時具有g(shù)etter和setter方法废赞,那么它是一個讀/寫屬性碑幅。如果它只有g(shù)etter方法,那么它是一個只讀屬性桐臊。如果它只有setter方法惨撇,那么它是一個只寫屬性伊脓。讀取只寫屬性總是返回undefined。
可枚舉性(enumerable)
可枚舉性決定屬性是否出現(xiàn)在對象的屬性枚舉中魁衙,具體來說报腔,for-in循環(huán)
、Object.keys()
纺棺、JSON.stringify()
是否會取到該屬性。
用戶定義的普通屬性默認(rèn)是可枚舉的邪狞,而原生繼承的屬性默認(rèn)是不可枚舉的祷蝌。
對象拷貝
對象拷貝分為淺拷貝(shallow)和深拷貝(deep)兩種。淺拷貝只復(fù)制一層對象的屬性帆卓,并不會進(jìn)行遞歸復(fù)制巨朦。深拷貝不僅將原對象的各個屬性逐個復(fù)制出去,而且將原對象各個屬性所包含的對象也依次采用深拷貝的方法遞歸復(fù)制到新對象上剑令,拷貝了所有層級糊啡。
淺拷貝
【方法一】簡單拷貝
??新建一個空對象,使用for-in循環(huán)吁津,將對象的所有屬性復(fù)制到新建的空對象中棚蓄。
function simpleClone1(obj){
if(typeof obj != 'object'){
return false;
}
var cloneObj = {};
for(var i in obj){
cloneObj[i] = obj[i];
}
return cloneObj;
}
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=simpleClone1(obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3,4]
【方法二】Object.assign()
Object.assign()
方法實行的是淺拷貝堕扶,而不是深拷貝。Object.assign()
方法可以接受任意數(shù)量的源對象梭依,并按指定的順序?qū)傩詮?fù)制到接收對象中稍算。在對象合并的過程中,Object.assign()
拷貝的屬性是有限制的役拴,只拷貝源對象的自身屬性(不拷貝繼承屬性)糊探,也不拷貝不可枚舉的屬性(enumerable: false。
var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
【方法三】使用屬性描述符
??通過對象的原型河闰,建立一個空的實例對象科平。通過forEach語句,獲取到對象的所有屬性的屬性描述符姜性,將其作為參數(shù)瞪慧,設(shè)置到新建的空實例對象中。本質(zhì)上跟方法一是一回事污抬,這種方法更為靈活汞贸,可以為對象屬性設(shè)置需要的描述符。
function simpleClone2(orig){
var copy = Object.create(Object.getPrototypeOf(orig));
Object.getOwnPropertyNames(orig).forEach(function(propKey){
var desc = Object.getOwnPropertyDescriptor(orig,propKey);
Object.defineProperty(copy,propKey,desc);
});
return copy;
}
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=simpleClone1(obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3,4]
【方法四】使用jquery的extend()方法印机,還可以用lodash等js庫矢腻。
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=$.extend({},obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3,4]
深拷貝
【方法一】遍歷復(fù)制
??復(fù)制對象的屬性時,對其進(jìn)行判斷射赛,如果是數(shù)組或?qū)ο蠖喔蹋瑒t再次調(diào)用拷貝函數(shù);否則楣责,直接復(fù)制對象屬性竣灌。
function deepClone1(obj,cloneObj){
if(typeof obj != 'object'){
return false;
}
var cloneObj = cloneObj || {};
for(var i in obj){
if(typeof obj[i] === 'object'){
cloneObj[i] = (obj[i] instanceof Array) ? [] : {};
arguments.callee(obj[i],cloneObj[i]); // 遞歸
}else{
cloneObj[i] = obj[i];
}
}
return cloneObj;
}
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=deepClone1(obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3]
【方法二】json
??用JSON全局對象的parse和stringify方法來實現(xiàn)深復(fù)制算是一個簡單討巧的方法,它能正確處理的對象只有Number秆麸、String初嘹、Boolean、Array沮趣、扁平對象屯烦,即那些能夠被json直接表示的數(shù)據(jù)結(jié)構(gòu)。
function jsonClone(obj){
return JSON.parse(JSON.stringify(obj));
}
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=jsonClone(obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3]
【方法三】使用jquery的extend()方法
var obj1={a:1,b:2,c:[1,2,3]};
var obj2=$.extend(true,{},obj1);
console.log(obj1.c); //[1,2,3]
console.log(obj2.c); //[1,2,3]
obj2.c.push(4);
console.log(obj2.c); //[1,2,3,4]
console.log(obj1.c); //[1,2,3]