likes
comments
collection
share

重学前端 js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

作者站长头像
站长
· 阅读数 25

今天菜鸟整理自己的 goole 书签栏,突然发现,看着确实挺有用,通过标题大致就知道是什么内容,大致就知道了什么时候可以帮助菜鸟解决什么问题,没用的或者太简单的就删除了。

但是菜鸟转念一想,发现菜鸟脑子里是一点印象都没有,如果用的时候来找的话,找得到还好,找不到就像考试作弊,明明考试前还看见了,但是一到考试就找不到答案在哪里的感觉,心态直接炸了。

而且感觉一些基础,即使不好记,也真的需要记在脑子里,而不是书签里,所以就把几个菜鸟感觉很重要、很常用的,这里做个总结,俗话说:好记性不如烂笔头,也希望可以帮助读者!

js 常见报错

建议熟悉单词:

  • Invalid 无效
  • unexpected 意外的
  • defined 未定义
  • property 属性

也要熟记这后面的几个错误单词!!!

1.1 SyntaxError(语法错误)

解析代码时发生的语法错误

var 1a;   //Uncaught SyntaxError: Invalid or unexpected token 无效或意外的标识符 - 变量名错误
console.log 'hello');  //Uncaught SyntaxError: Unexpected string 意外的字符串 - 缺少括号

1.2 ReferenceError(引用错误)

console.log(a);  //Uncaught ReferenceError: a is not defined a未定义 - 引用了一个不存在的变量
console.log()= 1;  //Uncaught ReferenceError: Invalid left-hand side in assignment 将变量赋值给一个无法被赋值的对象

1.3 RangeError(范围错误)

var a = new Array(-1);  //Uncaught RangeError: Invalid array length 无效长度 - 超出有效范围

1.4 TypeError(类型错误)

变量或参数不是预期类型,比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数

var a = new 123;  //Uncaught TypeError: 123 is not a function

调用不存在的方法

var a;
a.aa();  //Uncaught TypeError: Cannot read property 'aa' of undefined

1.5 URLError(URL错误)

与url相关函数参数不正确,主要是encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。

decodeURI('%2')  //Uncaught URIError: URI malformed at decodeURI

1.6 手动抛出错误

以上这 5 种派生错误,连同原始的Error对象都是构造函数。开发者可以使用它们,人为生成错误对象的实例。

throw new Error("出错了!"); 
throw new RangeError("出错了,变量超出有效范围!"); 
throw new TypeError("出错了,变量类型无效!");

上面代码表示新建错误对象的实例,实质就是手动抛出错误。可以看到,错误对象的构造函数接受一个参数(可以是对象),代表错误提示信息。

菜鸟还有一种报错没总结,感觉常用,更多参考:JS中常见的几种报错类型

js 获取数据类型

js 的数据类型

ES6以前。6种:Undefined、Null、Number、Boolean、String、Object ES6标准。7种:Undefined、Null、Number、Boolean、String、Symbol、Object ES2020标准。8种:Undefined、Null、Number、Boolean、String、Symbol、BigInt、Object

以下是用于测试的各种类型(不包括 BigInt 类型):

var a = 123,
  b = true,
  c = "123",
  d = undefined,
  e = null;
var o = new Object();
var f = new Function();
var f1 = function () {};
function f2() {}
var arr = [];
var arr1 = new Array();
var reg = new RegExp();
var sy = Symbol();

1.1 typeof

可以判断 js 中基本数据类型,但无法判断对象的具体类型

代码:

console.log("a:" + typeof a);
console.log("b:" + typeof b);
console.log("c:" + typeof c);
console.log("d:" + typeof d);
console.log("e:" + typeof e);
console.log("o:" + typeof o);
console.log("f:" + typeof f);
console.log("f1:" + typeof f1);
console.log("f2:" + typeof f2);
console.log("arr:" + typeof arr);
console.log("arr1:" + typeof arr1);
console.log("reg:" + typeof reg);
console.log("sy:" + typeof sy);

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

注意

当使用基本包装类型创建字符串、数组或布尔值时,使用typeof返回的是Object

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

判断基本类型

function ccTypeof(cc){
  return cc === null ? "null" : typrof(cc);
}

1.2 Object.prototype.toString.call()

可以判断具体的对象类型,包括正则等

代码:

console.log("a:" + Object.prototype.toString.call(a));
console.log("b:" + Object.prototype.toString.call(b));
console.log("c:" + Object.prototype.toString.call(c));
console.log("d:" + Object.prototype.toString.call(d));
console.log("e:" + Object.prototype.toString.call(e));
console.log("o:" + Object.prototype.toString.call(o));
console.log("f:" + Object.prototype.toString.call(f));
console.log("f1:" + Object.prototype.toString.call(f1));
console.log("f2:" + Object.prototype.toString.call(f2));
console.log("arr:" + Object.prototype.toString.call(arr));
console.log("arr1:" + Object.prototype.toString.call(arr1));
console.log("reg:" + Object.prototype.toString.call(reg));
console.log("sy:" + Object.prototype.toString.call(sy));

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

注意

无法判断自定义对象类型

function A() {
  return 111;
}
var x = new A();
console.log(Object.prototype.toString.call(x));

该代码结果为

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

而不是预期的 A

1.3 instanceof

用法:变量 instaceof 对象,返回值为boolean

仅能判断对象类型的具体类型,undefined 和 null 报错,但可以拥于判断自定义对象类型。

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

改成小写也不行,报错:

Uncaught TypeError: Right-hand side of 'instanceof' is not an object

null 同理!

代码:

console.log(a instanceof Number);
console.log(b instanceof Boolean);
console.log(c instanceof String);
console.log(o instanceof Object);
console.log(f instanceof Function);
console.log(f1 instanceof Function);
console.log(f2 instanceof Function);
console.log(arr instanceof Array);
console.log(arr1 instanceof Array);
console.log(reg instanceof RegExp);
console.log(sy instanceof Symbol);

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

判断自定义类型

代码:

function A(){
 this.a = 1;
}
function B(){
 this.b = 2;
}
var x = new A();
if(x instanceof A){
  console.log("x is A");  
}
if(x instanceof B){
  console.log("x is B");  
}else{
  console.log("x is not B"); 
}

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

1.4 constructor

查看对象对应的构造函数,object 的每个实例都具有属性 constructor,保存着用于创建当前对象的函数,和 instaceof 一样,undefined 和 null 报错,但是比 instaceof 功能更强大。

代码:

console.log(a.constructor === Number);
console.log(b.constructor === Boolean);
console.log(c.constructor === String);
console.log(o.constructor === Object);
console.log(f.constructor === Function);
console.log(f1.constructor === Function);
console.log(f2.constructor === Function);
console.log(arr.constructor === Array);
console.log(arr1.constructor === Array);
console.log(reg.constructor === RegExp);
console.log(sy.constructor === Symbol);

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

判断自定义类型

代码:

function A() {
  this.a = 1;
}
function B() {
  this.b = 2;
}
var x = new A();
if (x.constructor == A) {
  console.log("x is A");
}
if (x.constructor == B) {
  console.log("x is B");
} else {
  console.log("x is not B");
}

结果:

重学前端  js 常见报错 | js 获取数据类型 | js 判断是否是数组(第三十一天)

封装打印所有类型

function ccTypeof(cc){
  var typeName == Object.prototype.toString.call(cc);
  if( typeName == "[object Object]"){
      typeName = "[object" + cc.constructor.name + "]";
   }
}

js 判断是否是数组

有了上述学习,可以轻易的知道有 3 种方式可以知道是否为 Array ,分别为:Object.prototype.toString.call()、instanceof 、constructor,但是其实 instanceof 、constructor 不是特别好。

instanceof、constructor不好的原因

instanceof 运算符用于检验构造函数的 prototype 属性是否出现在对象的原型链中的任何位置,返回一个布尔值。

需要注意的是,prototype 属性是可以修改的,所以并不是最初判断为true就一定永远为真

其次,当我们的脚本拥有多个全局环境,例如:html中拥有多个iframe对象,instanceof的验证结果可能不会符合预期

//为body创建并添加一个iframe对象
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[0].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3); 
arr instanceof Array;//false

导致这种问题是因为 iframe 会产生新的全局环境,它也会拥有自己的 Array.prototype 属性,让不同环境下的属性相同很明显是不安全的做法,所以 Array.prototype !== window.frames[0].Array.prototype,想要 arr instanceof Array 为 true,你得保证 arr 是由原始 Array 构造函数创建时才可行。

constructor 也有该问题!

isArray

虽然 Object.prototype.toString.call() 没有上述问题,但是这么长的一串确实不好记,其实 js 已经考虑到了这些,所以为我们提供了更加方便的方法:isArray!

简单好用,而且对于多全局环境,Array.isArray() 同样能准确判断,但有个问题,Array.isArray() 是在ES5中提出,也就是说在ES5之前可能会存在不支持此方法的情况。

封装方法

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
转载自:https://juejin.cn/post/7376544418688139298
评论
请登录