如何判斷 ECMAScript 的變數型別 ?
栏目: JavaScript · 发布时间: 6年前
内容简介:ECMAScript 雖然是 Dynamic Language,但並不代表 Variable 沒有 Type,只是其內建獲得 Type 的方式包含太多VS Code 1.33.0Quokka 1.0.205
ECMAScript 雖然是 Dynamic Language,但並不代表 Variable 沒有 Type,只是其內建獲得 Type 的方式包含太多 驚喜 ,成為備受爭議的部分。本文整理出 4 種獲得 Type 方式,各有其優缺點,最後整理出自己的 typeof() ,可以判斷出各種 Type。
Version
VS Code 1.33.0
Quokka 1.0.205
ECMAScript 5
Ramda 0.26.1
Type
本文將介紹 5 種獲得 Type 方法:
typeof instanceof Object.prototype.toString() is() typeof()
Number
Number 共有 3 種建立方法:
- Number literal
- Number function
- Number constructor
實務上最常使用的是的 number literal,轉型時會使用 number function (或使用 + operator),但 number constructor 實務上不建議使用。
import { is } from 'ramda';
/** typeof */
console.log(typeof 1);
console.log(typeof Number(1));
console.log(typeof new Number(1));
/** instanceof */
console.log(1 instanceof Number);
console.log(Number(1) instanceof Number);
console.log(new Number(1) instanceof Number);
/** Object.prototype.toString() */
console.log(Object.prototype.toString.call(1));
console.log(Object.prototype.toString.call(Number(1)));
console.log(Object.prototype.toString.call(new Number(1)));
/** is() */
console.log(is(Number, 1));
console.log(is(Number, Number(1)));
console.log(is(Number, new Number(1)));
typeof
number object
instanceof
false true
instanceof 的邏輯理論上沒錯,但使得 typeof 與 instanceof 都有其不足,無法同時判斷 literal、function 與 constructor 所建立的 number,實務上並不好用
Object.prototype.toString()
- 無論對於 literal、function、constructor 所產生的 number,都回傳
number
Ramda 之 is()
- 無論對於 literal、function、constructor 所產生的 number,都回傳
true
Object.prototype.toString() 與 is() 都能同時判斷 literal、function 與 constructor 所產生的 number,實務上比較好用
String
String 共有 3 種建立方法:
- String literal
- String function
- String constructor
實務上最常使用的是的 string literal,轉型時會使用 string function (或使用 + '' operator),但 string constructor 實務上不建議使用。
import { is } from 'ramda';
/** typeof */
console.log(typeof 'abc');
console.log(typeof String('abc'));
console.log(typeof new String('abc'));
/** instanceof */
console.log('abc' instanceof String);
console.log(String('abc') instanceof String);
console.log(new String('abc') instanceof String);
/** Object.prototype.toString() */
console.log(Object.prototype.toString.call('abc'));
console.log(Object.prototype.toString.call(String('abc')));
console.log(Object.prototype.toString.call(new String('abc')));
/** is() */
console.log(is(String, 'abc'));
console.log(is(String, String('abc')));
console.log(is(String, new String('abc')));
typeof
string object
instanceof
false true
instanceof 的邏輯理論上沒錯,但使得 typeof 與 instanceof 都有其不足,無法同時判斷 literal、function 與 constructor 所建立的 string,實務上並不好用
Object.prototype.toString()
- 無論對於 literal、function、constructor 所產生的 string,都回傳
string
Ramda 之 is()
- 無論對於 literal、function、constructor 所產生的 string,都回傳
true
Object.prototype.toString() 與 is() 都能同時判斷 literal、function 與 constructor 所產生的 string,實務上比較好用
Boolean
Boolean 共有 3 種建立方法:
- Boolean literal
- Boolean function
- Boolean constructor
實務上最常使用的是的 boolean literal,轉型時會使用 boolean function (或使用 !! operator,且 ECMAScript 支援 boolean coercion,會自動轉型),但 boolean constructor 實務上不建議使用。
import { is } from 'ramda';
console.log(typeof true);
console.log(typeof Boolean(true));
console.log(typeof new Boolean(true));
console.log(true instanceof Boolean);
console.log(Boolean(true) instanceof Boolean);
console.log(new Boolean(true) instanceof Boolean);
console.log(Object.prototype.toString.call(true));
console.log(Object.prototype.toString.call(Boolean(true)));
console.log(Object.prototype.toString.call(new Boolean(true)));
console.log(is(Boolean, true));
console.log(is(Boolean, Boolean(true)));
console.log(is(Boolean, new Boolean(true)));
typeof
boolean object
instanceof
false true
instanceof 的邏輯理論上沒錯,但使得 typeof 與 instanceof 都有其不足,無法同時判斷 literal、function 與 constructor 所建立的 boolean,實務上並不好用
Object.prototype.toString()
- 無論對於 literal、function、constructor 所產生的 boolen,都回傳
boolean
Ramda 之 is()
- 無論對於 literal、function、constructor 所產生的 boolean,都回傳
true
Object.prototype.toString() 與 is() 都能同時判斷 literal、function 與 constructor 所產生的 boolean,實務上比較好用
Undefined
undefined 在 ECMAScript 已獨立成一個 type,其值也是 undefined 。
import { isNil } from 'ramda';
/** typeof */
console.log(typeof undefined);
/** instanceof */
// N/A
/** Object.prototype.toString() */
console.log(Object.prototype.toString.call(undefined));
/** isNil() */
console.log(isNil(undefined));
typeof
- 判斷
undefined會如預期回傳undefined
instanceof
- 無法判斷
undefined,因為不存在 undefined constructor
Object.prototype.toString()
- 判斷
undefined會如預期回傳undefined
isNil()
-
is()無法判斷undefined,要改用isNil(),如預期回傳true
Ramda 使用 isNil() 使得 type 判斷分裂成兩個 function,實務上沒那麼好用,目前只有 Object.prototype.toString() 能達到單一 function 判斷所有 type
Null
null 在 ECMAScript 已獨立成一個 type,其值也是 null 。
import { isNil } from 'ramda';
/** typeof */
console.log(typeof null);
/** instanceof */
// N/A
/** Object.prototype.toString() */
console.log(Object.prototype.toString.call(null));
/** isNil() */
console.log(isNil(null));
typeof
- 判斷
null會如預期回傳object,這是已知的 bug,但因為歷史因素,無法修改,變成 feature
instanceof
- 無法判斷
null,因為不存在 null constructor
Object.prototype.toString()
- 判斷
null會如預期回傳null
isNil()
-
is()無法判斷null,要改用isNil(),如預期回傳true
Ramda 使用 isNil() 使得 type 判斷分裂成兩個 function,實務上沒那麼好用,目前只有 Object.prototype.toString() 能達到單一 function 判斷所有 type
Object
Object 共有 5 種建立方法:
- Object literal
- Object constructor
- Constructor function
- Class
- Object.create()
實務上最常使用的是的 object literal,而 constructor function、class 與 Object.create() 都有其適用時機,但 object constructor 實務上不建議使用。
/** object literal */
console.log(typeof {});
/** object constructor */
console.log(typeof new Object());
/** constructor function */
function Foo1() {}
console.log(typeof new Foo1());
/** class */
class Foo2 {}
console.log(typeof new Foo2());
/** Object.create() */
console.log(typeof Object.create({}));
typeof
- 無論使用哪一種方式建立 object,都會如預期回傳
object
/** object literal */
console.log({} instanceof Object);
/** object constructor */
console.log(new Object() instanceof Object);
/** constructor function */
function Foo1() {}
console.log(new Foo1() instanceof Object);
/** class */
class Foo2 {}
console.log(new Foo2() instanceof Object);
/** Object.create() */
console.log(Object.create({}) instanceof Object);
instanceof
- 無論使用哪一種方式建立 object,都會如預期回傳
true
/** object literal */
console.log(Object.prototype.toString.call({}));
/** object constructor */
console.log(Object.prototype.toString.call(new Object()));
/** constructor function */
function Foo1() {}
console.log(Object.prototype.toString.call(new Foo1()));
/** class */
class Foo2 {}
console.log(Object.prototype.toString.call(new Foo2()));
/** Object.create() */
console.log(Object.prototype.toString.call(Object.create({})));
Object.prototype.toString()
- 無論使用哪一種方式建立 object,都會如預期回傳
object
import { is } from 'ramda';
/** object literal */
console.log(is(Object, {}));
/** object constructor */
console.log(is(Object, new Object()));
/** constructor function */
function Foo1() {}
console.log(is(Object, new Foo1()));
/** class */
class Foo2 {}
console.log(is(Object, new Foo2()));
/** Object.create() */
console.log(is(Object, Object.create({})));
is()
- 無論使用哪一種方式建立 object,都會如預期回傳
true
對於 object,無論使用 typeof 、 instanceof 、 Object.prototype.toString() 或 is() ,都可以如預期判斷出 object
Array
Array 共有 3 種建立方法:
- Array literal
- Array function
- Array constructor
實務上最常使用的是的 array literal,建立 empty array 時會使用 array function,但 array constructor 實務上不建議使用 (因為效果與 array function 一樣)。
import { is } from 'ramda';
/** typeof */
console.log(typeof []);
console.log(typeof Array(0));
console.log(typeof new Array(0));
/** instanceof */
console.log([] instanceof Array);
console.log(Array(0) instanceof Array);
console.log(new Array(0) instanceof Array);
/** Object.prototype.toString() */
console.log(Object.prototype.toString.call([]));
console.log(Object.prototype.toString.call(Array(0)));
console.log(Object.prototype.toString.call(new Array(0)));
/** is() */
console.log(is(Array, []));
console.log(is(Array, Array(0)));
console.log(is(Array, new Array(0)));
typeof
- 無論使用哪一種方式建立 array,都無法如預期回傳
array,而是回傳object,這是比較困擾的地方
instanceof
- 無論使用哪一種方式建立 object,都會如預期回傳
true
Object.prototype.toString()
- 無論對於 literal、function、constructor 所產生的 array,都回傳
array
Ramda 之 is()
- 無論對於 literal、function、constructor 所產生的 array,都回傳
true
instanceof 、 Object.prototype.toString() 與 is() 都能同時判斷 literal、function 與 constructor 所產生的 array,實務上比較好用,但 typeof 則完全誤判為 object
Function
Function 共有 4 種建立方法:
- Function declaration
- Function expression
- Function constructor
- Arrow function
實務上最常使用的是的 function expression 與 arrow function,function declaration 則漸漸較少使用,但 function constructor 使用機會更少,除非想在 run-time 動態湊出 function。
/** function declaration */
function fun() {}
console.log(typeof fun);
/** function expression */
console.log(typeof function() {});
/** function constructor */
console.log(typeof new Function());
/** arrow function */
console.log(typeof (() => {}));
typeof
- 無論使用哪一種方式建立 function,都會如預期回傳
function
/** function declaration */
function fun() {}
console.log(fun instanceof Function);
/** function expression */
console.log(function() {} instanceof Function);
/** function constructor */
console.log(new Function() instanceof Function);
/** arrow function */
console.log((() => {}) instanceof Function);
instanceof
- 無論使用哪一種方式建立 function,都會如預期回傳
true
/** function declaration */
function fun() {}
console.log(Object.prototype.toString.call(fun));
/** function expression */
console.log(Object.prototype.toString.call(function() {}));
/** function constructor */
console.log(Object.prototype.toString.call(new Function()));
/** arrow function */
console.log(Object.prototype.toString.call(() => {}));
Object.prototype.toString()
- 無論使用哪一種方式建立 function,都會如預期回傳
function
import { is } from 'ramda';
/** function declaration */
function fun() {}
console.log(is(Function, fun));
/** function expression */
console.log(is(Function, function() {}));
/** function constructor */
console.log(is(Function, new Function()));
/** arrow function */
console.log(is(Function, () => {}));
is()
- 無論使用哪一種方式建立 object,都會如預期回傳
true
對於 function,無論使用 typeof 、 instanceof 、 Object.prototype.toString() 或 is() ,都可以如預期判斷出 function
typeof()
let typeof = data => Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
console.log(typeof(1));
console.log(typeof(new Number(1)));
console.log(typeof(new String('abc')));
console.log(typeof(new String('abc')));
console.log(typeof(true));
console.log(typeof(new Boolean(true)));
console.log(undefined);
console.log(null);
console.log(typeof({}));
console.log(typeof([]));
console.log(typeof(()=>{}));
根據以上經驗,我們發現只有一種方式能抓到所有 type 都正確,那就是 Object.prototype.toString() ,但其回傳還包含 [Object ] 等不需要部分,且 type 是第一個字大寫,因此只要稍作加工,就可以與 typeof 完全一樣。
let typeof = data => Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
一樣使用 Object.prototype.toString() ,利用 slice() 抓到我們要的部分,最後再 toLowerCase() 轉成全小寫。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
How to Build a Billion Dollar App
George Berkowski / Little, Brown Book Group / 2015-4-1 / USD 24.95
Apps have changed the way we communicate, shop, play, interact and travel and their phenomenal popularity has presented possibly the biggest business opportunity in history. In How to Build a Billi......一起来看看 《How to Build a Billion Dollar App》 这本书的介绍吧!