安全數(shù)據(jù)類型監(jiān)測(cè)
typeof
: 由于一些無法預(yù)知的情況剥纷, 用這種方式會(huì)得到不靠譜的結(jié)果。
instanceof
: 必須在同一全局執(zhí)行環(huán)境 [高程:596]
Object.prototype.toString.call(d).slice(8, -1);
作用域安全的構(gòu)造函數(shù)
構(gòu)造函數(shù)就是使用new
操作符調(diào)用的函數(shù)伟姐。當(dāng)使用new
時(shí),構(gòu)造函數(shù)內(nèi)用到的this
會(huì)指向新創(chuàng)建的對(duì)象實(shí)例。
但當(dāng)沒用使用new
操作符調(diào)用構(gòu)造函數(shù)時(shí)付魔,由于該this
對(duì)象是在運(yùn)行時(shí)綁定的,所以直接調(diào)用 Person()飞蹂,this
會(huì)映射到window
上几苍,導(dǎo)致錯(cuò)誤對(duì)象屬性的意外增加。
function Person(name, age) {
this.name = name;
this.age = age;
}
var p1 = new Person('sunorry', 18);
var p2 = Person('machao', 28);
window.age; // 28
p2.age; // Error
原本只對(duì) Person 實(shí)例的三個(gè)屬性被加到 window
對(duì)象上陈哑,因?yàn)?strong>構(gòu)造函數(shù)是作為普通函數(shù)調(diào)用的妻坝,忽略了new
操作符。由于 window
的 name
屬性適用于識(shí)別鏈接目標(biāo)和 frame
的惊窖,所以這里對(duì)該屬性的偶然覆蓋可能會(huì)導(dǎo)致該頁面上出現(xiàn)錯(cuò)誤刽宪。
實(shí)現(xiàn)了上面的模式后,你就鎖定了可以調(diào)用的構(gòu)造函數(shù)的環(huán)境爬坑。如果你使用構(gòu)造函數(shù)竊取模式的繼承且不使用原型鏈纠屋,那么這個(gè)繼承可能被破壞。
function Polygon(sides) {
if(this instanceof Polygon) {
this.sides = sides;
this.getArea = function() {
return 0;
}
} else {
return new Polygon(sides);
}
}
function Rectangle(width, height) {
Polygon.call(this, 2);
this.width = width;
this.height = height;
this.getArea = function() {
return this.width * this.height;
};
}
var rect = new Rectangle(5, 10);
console.log(rect.sides); //undefiend
Polygon 構(gòu)造函數(shù)是作用域安全的盾计,然而 Rectangle 構(gòu)造函數(shù)則不是售担。新創(chuàng)建個(gè) Rectangle 實(shí)例之后趋惨,這個(gè)實(shí)例應(yīng)該通過 Polygon.call()
來繼承 Polygon 的 sildes 屬性仅胞。但是短条,由于 Polygon 是構(gòu)造函數(shù)是作用域安全的恭朗, this
對(duì)象并非 Polygon 的實(shí)例,所以會(huì)創(chuàng)建并返回一個(gè)新的 Polygon 對(duì)象哥攘。 Rectangle 構(gòu)造函數(shù)中的 this
并沒用得到增長(zhǎng)剖煌,同時(shí) Polygon.call() 返回的值也沒有得到,所以 Rectangle 實(shí)例中就不會(huì)有 sides 屬性逝淹。
如果構(gòu)造函數(shù)竊取結(jié)合使用原型鏈或者寄生組合則可以解決這個(gè)問題耕姊。
在 new
之前加上
Rectangle.prototype = new Rolygon();
一個(gè) Rectangle 實(shí)例也同時(shí)是一個(gè) Polygon 實(shí)例,所以 Polygon.call() 會(huì)照愿意執(zhí)行栅葡,做種為 Rectangle 實(shí)例添加了 sides 屬性茉兰。