typeof
對一個值使用typeof操作符可能返回:
undefined、string、number、boolean、symbol、object(對象或null)、function
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object []數組的數據類型在 typeof 中被解釋爲object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object null 的數據類型被 typeof 解釋爲 object
typeof 對於基本類型,除了null都可以顯示正確的類型;對於對象,除了函數都會顯示object。
對於null來說,雖然它是基本類型,但是會顯示object,這是一個存在了很久的bug。
因爲在js的最初版本中,使用的是32位系統,爲了性能考慮使用低位存儲了變量的類型信息,000開頭代表是對象,然而null表示爲全零,所以將它錯誤的判斷爲object。雖然現在的內部類型 判斷代碼已經改變了,但是對於這個bug卻是一直流傳下來。
instanceof
只有引用數據類型(Array,Function,Object)被精準判斷,其他(數值Number,布爾值Boolean,字符串String)字面值不能被instanceof精準判斷。
instanceof可以正確的判斷對象的類型,因爲內部機制是通過判斷對象的原型鏈中是不是能找得類型的prototype。
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
// console.log(undefined instanceof Undefined);
// console.log(null instanceof Null);
function Person(name, age) {
this.name = name;
this.age = age;
}
function Dog(name, age) {
this.name = name;
this.age = age;
}
var p = new Person('zs', 18);
var d = new Dog('小花', 8);
console.log(p instanceof Person); // true
console.log(d instanceof Person); // true
console.log(p instanceof Object); // false
constructor
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
用costructor來判斷類型看起來是完美的,然而,如果我創建一個對象,更改它的原型,這種方式也變得不可靠了。
function Person(name, age) {
this.name = name;
this.age = age;
}
var p = new Person('csm', 21);
console.log(p.constructor.name); // Person
// 改變原型
Person.prototype = {
name: 'zs',
age: 18
};
var p1 = new Person('csm', 21);
console.log(p1.constructor.name); // Object
因此,當要修改對象的proptotype時,一定要設置constructor指向其構造函數
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype = {
constructor: Person,
name: 'zs',
age: 18
};
var p = new Person('csm', 21);
console.log(p.constructor.name); // Person
object.prototype.toString.call()
console.log(Object.prototype.toString.call(2)); // [object Number]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call('str')); // [object String]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(function(){})); // [object Function]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(null)); // [object Null]
使用 Object 對象的原型方法 toString ,使用 call 進行狸貓換太子,借用Object的 toString 方法結果精準的顯示我們需要的數據類型。就算我們改變對象的原型,依然會顯示正確的數據類型。