JavaScript中typeof,instanceof洽胶,hasOwnProperty晒夹,in的用法和區(qū)別

一. typeof操作符

typeof操作符用于返回正在使用值的類型。

// 使用原始值
let mNull = null;
let mUndefined = undefined;
let mString = 'mazey';
let mNumber = 123;
let mBoolean = true;
let mFunction = function () {
    return true;
};

// 用構(gòu)造函數(shù)的方式new一個實例
let oString = new String('cherrie');
let oRegExp = new RegExp('^[0-9]+$');
let oFunction = new Function('x', 'y', 'return x + y');

let oObj = {};
let oNew = new Object();

// typeof值
console.log(typeof mNull); // object
console.log(typeof mUndefined); // undefined
console.log(typeof mString); // string
console.log(typeof mNumber); // number
console.log(typeof mBoolean); // boolean
console.log(typeof mFunction); // function
console.log(typeof oString); // object
console.log(typeof oRegExp); // object
console.log(typeof oFunction); // function
console.log(typeof oObj); // object
console.log(typeof oNew); // object

在《JavaScript啟示錄》中new RegExp()介紹會返回function姊氓,但是事實上我在chrome控制臺中看到的是object丐怯。

于是我console.log(new RegExp('^[0-9]+$')),打印出來的是字符串/^[0-9]+$/翔横。

console.log(new RegExp('^[0-9]+$')); // /^[0-9]+$/
console.log(RegExp); // ? RegExp() { [native code] } 原始值
console.log(String); // ? String() { [native code] } 原始值
console.log(/^[0-9]+$/); // /^[0-9]+$/
console.log(new RegExp('^[0-9]+$') === /^[0-9]+$/); // false
console.log(RegExp('^[0-9]+$') === /^[0-9]+$/); // false

綜上可以看出現(xiàn)版本RegExpString Number一樣屬于JavaScript的原始值读跷。

Math作為JavaScript中的靜態(tài)對象回返回什么呢?

console.log(typeof Math); // object
console.log(typeof Math.PI); // number
console.log(typeof Math.ceil); // function

所以Math__proto__還是Object禾唁,typeof還能返回對象的屬性和方法的類型效览。

typeof使用場景

  1. 判斷某個變量是否已定義
console.log(typeof aaa); // 'undefined'

// 判斷
if (typeof bbb === 'undefined') {
    console.log('變量未定義');
}
  1. 區(qū)分原始值和復(fù)雜值(對象值)

因為復(fù)雜值往往返回object,當(dāng)然有個例外就是原始值里面的null也返回object荡短,然后function作為Object的實例也是復(fù)雜值丐枉。

// 判斷是否時復(fù)雜值(對象值)
function isObject (m) {
    return (typeof m === 'function' || (typeof m === 'object' && m !== null));
}

console.log(isObject(new RegExp('123'))); // true
console.log(isObject('123')); // false
console.log(isObject(String('123'))); // false
console.log(isObject(null)); // false

// 判斷是否是原始值
function isNative (m) {
    return (m === null || (typeof m !== 'object' && typeof m !== 'function'));
}

console.log(isNative(new RegExp('123'))); // false
console.log(isNative('123')); // true
console.log(isNative(String('123'))); // true
console.log(isNative(null)); // true
  1. 檢測某個變量是否是函數(shù)

當(dāng)使用閉包時判斷是函數(shù)后再進(jìn)行下一步。

function qqq () {
    let a = 0;
    let b = function () {
        a++;
        console.log(a);
    };
    return b;
}

let ccc = qqq();
console.log(typeof ccc); // function
if (typeof ccc === 'function') {
    ccc(); // 1
    ccc(); // 2
    ccc(); // 3
    ccc(); // 4
}

二. instanceof操作符

通過使用instanceof操作符掘托,可以確定一個對象是否是特定構(gòu)造函數(shù)實例瘦锹,返回truefalse

instanceof只適用于構(gòu)造函數(shù)創(chuàng)建返回的復(fù)雜對象實例

任何時間判斷一個對象(復(fù)雜值)是否是Object的實例時弯院,它都將返回true辱士,因為所有對象都繼承自Object()構(gòu)造函數(shù)。

let oFather = function () {
    this.firstName = 'mazey';
};
oFather.prototype.lastName = 'qian';

// 實例
let oSon = new oFather();
console.log(oSon instanceof oFather); // true

// 繼承
let nFather = function () {};
nFather.prototype = new oFather();
nFather.construction = nFather;
console.log(nFather.firstName); // undefined
console.log(nFather.prototype.lastName); // qian
console.log(nFather instanceof oFather); // false
console.log(new nFather() instanceof nFather); // true

// 相對于Object來說
console.log('123' instanceof Object); // false
console.log(new String('123') instanceof Object); // true 構(gòu)造出來的實例
console.log(null instanceof Object); // false

instanceof使用場景

判斷在一個繼承關(guān)系中實例是否屬于它的父類听绳。

// 繼承
let oFather = function () {};
let nFather = function () {};
nFather.prototype = new oFather();
nFather.construction = nFather;

let nSon = new nFather();
console.log(nSon instanceof nFather); // true
console.log(nSon instanceof oFather); // true

三. in操作符和hasOwnProperty方法

in操作符可以檢查一個對象的屬性颂碘,包括來自原型鏈的屬性,hasOwnProperty()方法可以檢查來自非原型鏈屬性的對象辫红。

例如現(xiàn)在有一個對象let obj = {name: 'mazey'};凭涂,name是它自身定義的屬性,toString是它從原型鏈上繼承下來的屬性贴妻。

let obj = {name: 'mazey'};
console.log('name' in obj); // true
console.log('toString' in obj); // true
console.log('name' in Object); // true
console.log(obj.hasOwnProperty('name')); // true
console.log(obj.hasOwnProperty('toString')); // false
console.log(Object.hasOwnProperty('name')); // true

所以in操作符查找的范圍更廣一點切油,可以用hasOwnProperty()判斷是否是對象自身的屬性,而不是通過類似obj.prototype.foo = 'foo';這樣定義的名惩。

hasOwnProperty方法使用場景

在實際項目中經(jīng)常使用for...in...來遍歷對象中可枚舉的屬性澎胡,但是for...in...常常把原型obj.prototype.xxx中的屬性也列舉出來,所以在循環(huán)的時候可以加上hasOwnProperty()方法判斷下娩鹉。

function obj0 () {
    this.name = 'mazey',
    this.age = '24'
};
obj0.prototype.gender = 'male';
let obj1 = new obj0();

// 打印所有可枚舉屬性
for (let key in obj1) {
    console.log(key); // name age gender 從原型鏈上繼承下來的屬性也會被打印出來
}

// 過濾掉原型鏈上的屬性
for (let key in obj1) {
    if (obj1.hasOwnProperty(key)) {
        console.log(key); // name age
    }
}

四. 總結(jié)

  1. typeof可以判斷使用值的類型攻谁,注意null返回object
  2. instanceof驗證構(gòu)造函數(shù)構(gòu)造出來的實例弯予,可以用來判斷一個對象是否屬于一個父類戚宦。
  3. hasOwnProperty方法常常與in操作符搭配使用,用來遍歷一個對象自身的屬性锈嫩。

五. 相關(guān)擴(kuò)展

1. 刪除對象的屬性

若想把一個對象的自身屬性完全刪除受楼,要使用delete操作符。

let obj0 = {
    name: 'mazey',
    age: 24
};

// 刪除age屬性
delete obj0.age;
console.log(obj0.hasOwnProperty('age')); // false
console.log('age' in obj0); // false

// 試著刪除原型鏈上的屬性 toString
delete obj0.toString
console.log('toString' in obj0); // true

需要注意的是delete不會刪除原型鏈上的屬性呼寸。

2. 可枚舉

每個對象的屬性都分為可枚舉和不可枚舉屬性艳汽,可以使用propertyIsEnumerable()方法來檢查哪些屬性是可枚舉的。

每個對象都有一個propertyIsEnumerable方法对雪。此方法可以確定對象中指定的屬性是否可以被for...in(for...in語句以任意順序遍歷一個對象的可枚舉屬性河狐。對于每個不同的屬性,語句都會被執(zhí)行)循環(huán)枚舉瑟捣,但是通過原型鏈繼承的屬性除外馋艺。如果對象沒有指定的屬性,則此方法返回false迈套。

有的資料說只要能被for..in遍歷的屬性就是可枚舉的丈钙,實際上要排除從原型鏈上繼承下來的屬性,只有自身的屬性是可枚舉的交汤。

// 第一個構(gòu)造函數(shù)
function ConFun0 () {
    this.firstName = 'mazey';
}
ConFun0.prototype.firstCom = 'bang';

// 第二個構(gòu)造函數(shù)
function ConFun1 () {
    this.secondName = 'qian';
}
// 繼承第一個
ConFun1.prototype = new ConFun0();
ConFun1.prototype.constructor = ConFun1;

// 實例
let obj = new ConFun1();
obj.girlName = 'cherrie';

// 是否可枚舉
console.log(obj.propertyIsEnumerable('constructor')); // false
console.log(obj.propertyIsEnumerable('firstName')); // false
console.log(obj.propertyIsEnumerable('firstCom')); // false
// 通過原型鏈繼承的屬性不是可枚舉
console.log(obj.propertyIsEnumerable('secondName')); // true
console.log(obj.propertyIsEnumerable('girlName')); // true

for (let key in obj) {
    console.log(key); // secondName girlName (原型鏈上的屬性也會被打印出來->) firstName constructor firstCom
}

console.log(`---分割線---`);

for (let key in obj) {
    // 過濾掉原型鏈上的屬性
    if (obj.hasOwnProperty(key)) {
        console.log(key); // secondName girlName
    }
}

所以可枚舉的屬性一定能被for..in循環(huán)遍歷出來,但是for...in循環(huán)遍歷出來的屬性不一定是可枚舉的,需排除從原型鏈上繼承下來的屬性芙扎,這里可以通過hasOwnProperty()方法過濾掉不可枚舉屬性星岗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市戒洼,隨后出現(xiàn)的幾起案子俏橘,更是在濱河造成了極大的恐慌,老刑警劉巖圈浇,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寥掐,死亡現(xiàn)場離奇詭異,居然都是意外死亡磷蜀,警方通過查閱死者的電腦和手機(jī)召耘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褐隆,“玉大人污它,你說我怎么就攤上這事∈” “怎么了衫贬?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長歇攻。 經(jīng)常有香客問我固惯,道長,這世上最難降的妖魔是什么缴守? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任葬毫,我火速辦了婚禮,結(jié)果婚禮上斧散,老公的妹妹穿的比我還像新娘供常。我一直安慰自己,他們只是感情好鸡捐,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布栈暇。 她就那樣靜靜地躺著,像睡著了一般箍镜。 火紅的嫁衣襯著肌膚如雪源祈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天色迂,我揣著相機(jī)與錄音香缺,去河邊找鬼。 笑死歇僧,一個胖子當(dāng)著我的面吹牛图张,可吹牛的內(nèi)容都是我干的锋拖。 我是一名探鬼主播,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼祸轮,長吁一口氣:“原來是場噩夢啊……” “哼兽埃!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起适袜,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤柄错,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后苦酱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體售貌,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年疫萤,在試婚紗的時候發(fā)現(xiàn)自己被綠了颂跨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡给僵,死狀恐怖毫捣,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帝际,我是刑警寧澤蔓同,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站蹲诀,受9級特大地震影響斑粱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脯爪,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一则北、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧痕慢,春花似錦尚揣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至塔次,卻和暖如春方篮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背励负。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工藕溅, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人继榆。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓巾表,卻偏偏與公主長得像汁掠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子攒发,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349