今回は主にJavaScriptの型判定関数typeofと判定コンストラクタプロトタイプinstanceofの使い方と注意点についてお話します。
typeof
まずtypeofについて話しましょう。まず注意すべきことは、typeof メソッド は データ の型を表す文字列 を返すということです。
構文の説明
まず、各データ型に対応する typeof の値を見てみましょう:
データ型 |
Type |
未定義 |
"未定義" |
ヌル |
” オブジェクト" |
ブール |
"ブール値" |
数値 |
"数値" |
文字列 |
"文字列" |
シンボル(ECMAの新機能)スクリプト 6) | 」シンボル" |
ホストオブジェクト(ブラウザなどのJS環境によって提供される) |
実装依存 |
関数オブジェクト |
"関数" |
その他のオブジェクト |
"オブジェクト" |
もう一度具体的な例を見てください:
// Numbers
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // 尽管NaN是"Not-A-Number"的缩写,意思是"不是一个数字"
typeof Number(1) === 'number'; // 不要这样使用!
// Strings
typeof "" === 'string';
typeof "bla" === 'string';
typeof (typeof 1) === 'string'; // typeof返回的肯定是一个字符串
typeof String("abc") === 'string'; // 不要这样使用!
// Booleans
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(true) === 'boolean'; // 不要这样使用!
// Symbols
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';
// Undefined
typeof undefined === 'undefined';
typeof blabla === 'undefined'; // 一个未定义的变量,或者一个定义了却未赋初值的变量
// Objects
typeof {a:1} === 'object';
// 使用Array.isArray或者Object.prototype.toString.call方法可以从基本的对象中区分出数组类型
typeof [1, 2, 4] === 'object';
typeof new Date() === 'object';
// 下面的容易令人迷惑,不要这样使用!
typeof new Boolean(true) === 'object';
typeof new Number(1) ==== 'object';
typeof new String("abc") === 'object';
// 函数
typeof function(){} === 'function';
typeof Math.sin === 'function';
ログイン後にコピー
問題が見つかります。つまり、typeof はデータ型を決定するのに正確ではありません。たとえば、配列、正規表現、日付、オブジェクトの戻り値の typeof はすべてオブジェクトであるため、エラーが発生します。
そのため、型を判断する typeof に基づいて、さらにデータ型を判断するために Object.prototype.toString メソッドを使用する必要もあります。
同じデータ型の場合の toString メソッドと typeof メソッドの戻り値の違いを見てみましょう:
data | toString | typeof |
"foo" | 文字列 | 文字列 |
新しい文字列("foo") | 文字列 | オブジェクト |
新しい数値(1.2) | 数値 | オブジェクト |
本当 | ブール値 | ブール値 |
new ブール値 (true) | ブール | オブジェクト |
new Date() | Date | object |
new | エラー | オブジェクト |
new Array(1, 2, 3) | Array | object |
/abc/g | RegExp | object |
new RegExp("meow") | RegExp | オブジェクト |
可以看到利用toString方法可以正确区分出Array、Error、RegExp、Date等类型。
所以我们一般通过该方法来进行数据类型的验证
真题检测
但是既然今天说到了typeof,那这里就列出几道题目,来看看自己是否真正掌握了typeof的用法。
第一题:
var y = 1, x = y = typeof x;
x;
ログイン後にコピー
第二题:
(function f(f){
return typeof f();
})(function(){ return 1; });
ログイン後にコピー
第三题:
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
ログイン後にコピー
第四题:
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();
ログイン後にコピー
第五题:
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;
ログイン後にコピー
第六题:
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
ログイン後にコピー
第七题:
(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });
ログイン後にコピー
ログイン後にコピー
下面公布答案了,这七题的答案分别是:
"undefined","number","undefined","undefined","number","1undefined","undefined"
ログイン後にコピー
做对了几道呢?是不是很大的困惑呢?这几题虽然都有typeof,但是考察了很多javascript的基础噢。下面我们来一一详解。
第一题:
var y = 1, x = y = typeof x;
x;//"undefined"
ログイン後にコピー
表达式是从右往左的,x由于变量提升,类型不是null,而是undefined,所以x=y=”undefined”。
变量提升我在这篇文章中提到过,可以看看。
第二题:
(function f(f){
return typeof f();//"number"
})(function(){ return 1; });
ログイン後にコピー
传入的参数为f也就是function(){ return 1; }这个函数。通过f()执行后,得到结果1,所以typeof 1返回”number”。这道题很简单,主要是区分f和f()。
第三题:
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();//"undefined"
})(foo.bar);
ログイン後にコピー
这一题考察的是this的指向。this永远指向函数执行时的上下文,而不是定义时的(ES6的箭头函数不算)。当arguments执行时,this已经指向了window对象。所以是”undefined”。对this执行不熟悉的同学可以看看这篇文章:深入理解this,对刚刚提到的箭头函数感兴趣的同学可以看看初步探究ES6之箭头函数。
第四题:
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();//undefined
ログイン後にコピー
如果上面那一题做对了,那么这一题也应该不会错,同样是this的指向问题。
第五题:
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;//"number"
ログイン後にコピー
这一题比较容易错,因为我在遇到这道题之前也从来没有遇到过javascript的分组选择符。什么叫做分组选择符呢?举一个例子就会明白了:
var a = (1,2,3);
document.write(a);//3,会以最后一个为准
ログイン後にコピー
所以上面的题目会返回2,typeof 2当然是”number”啦。
第六题:
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;//"1undefined"
ログイン後にコピー
这是一个javascript语言规范上的问题,在条件判断中加入函数声明。这个声明语句本身没有错,也会返回true,但是javascript引擎在搜索的时候却找不到该函数。所以结果为”1undefined”。
第七题:
(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });
ログイン後にコピー
ログイン後にコピー
这题其实是一个考察心细程度的题目。形参的foo指向的是{ foo: { bar: 1 } }这个整体。相信这么说就明白了。
好啦。上面的题目都是很好的资源噢。
instanceof
接下来该说说instanceof方法了。instanceof运算符可以用来判断某个构造函数的prototype属性是否存在于另外一个要检测对象的原型链上。
如果对原型不太了解,可以看看深入理解原型。
下面我们看看instanceof的实例:
// 定义构造函数
function C(){}
function D(){}
var o = new C();
// true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof C;
// false,因为 D.prototype不在o的原型链上
o instanceof D;
o instanceof Object; // true,因为Object.prototype.isPrototypeOf(o)返回true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype指向了一个空对象,这个空对象不在o的原型链上.
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true
ログイン後にコピー
但是这里我们需要注意一个问题:
function f(){ return f; }
document.write(new f() instanceof f);//false
function g(){}
document.write(new g() instanceof g);//true
ログイン後にコピー
第一个为什么返回false呢?因为构造函数的原型被覆盖了,我们可以看看new f和new g的区别:
以上がJavaScriptのtypeofとinstanceofの違いを深く理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
-
2023-03-15 16:54:01
-
2023-03-15 12:26:02
-
2023-03-14 18:58:01
-
2023-03-14 11:30:01
-
1970-01-01 08:00:00
-
2023-03-16 15:20:01
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00
-
1970-01-01 08:00:00