这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这次主要说说 javascript 的类型判断函数 typeof 和判断构造函数原型 instanceof 的用法和注意的地方,对本文感兴趣的朋友一起看看吧
这次主要说说 javascript 的类型判断函数 typeof 和判断构造函数原型 instanceof 的用法和注意的地方。
typeof
先来说说 typeof 吧。首先需要注意的是,typeof 方法返回一个字符串,来表示数据的类型。
typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型。
它返回值是一个字符串,该字符串说明运算数的类型。typeof 一般只能返回如下几个结果: number,boolean,string,function,object,undefined。我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错,对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。
语法讲解
我们先看看各个数据类型对应 typeof 的值:
数据类型 | Type |
---|---|
Undefined | "undefined" |
Null | "object" |
布尔值 | "boolean" |
数值 | "number" |
字符串 | "string" |
Symbol (ECMAScript 6 新增) | "symbol" |
宿主对象 (JS 环境提供的,比如浏览器) | Implementation-dependent |
函数对象 | "function" |
任何其他对象 | "object" |
再看看具体的实例:
- // 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 返回值都是 object,这就会造成一些误差。
所以在 typeof 判断类型的基础上,我们还需要利用 Object.prototype.toString 方法来进一步判断数据类型。
我们来看看在相同数据类型的情况下,toString 方法和 typeof 方法返回值的区别:
数据 | toString | typeof |
---|---|---|
"foo" | String | string |
new String("foo") | String | object |
new Number(1.2) | Number | object |
true | Boolean | boolean |
new Boolean(true) | Boolean | object |
new Date() | Date | object |
new Error() | Error | object |
new Array(1, 2, 3) | Array | object |
/abc/g | RegExp | object |
new RegExp("meow") | RegExp | object |
可以看到利用 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 用于判断一个变量是否某个对象的实例,如 var a=new Array();alert(a instanceof Array); 会返回 true,同时 alert(a instanceof Object) 也会返回 true; 这是因为 Array 是 object 的子类。再如:function test(){};var a=new test();alert(a instanceof test) 会返回
谈到 instanceof 我们要多插入一个问题,就是 function 的 arguments,我们大家也许都认为 arguments 是一个 Array,但如果使用 instaceof 去测试会发现 arguments 不是一个 Array 对象,尽管看起来很像。
如果对原型不太了解,可以看看深入理解原型。
下面我们看看 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 的区别:
来源: http://www.phperz.com/article/17/0411/267898.html