一、JS错误信息类型
(1)SyntaxError 语法错误
1.变量名不规范
var 1 = 1;
结果:
未被捕获的语法错误:意外的数字
var 1ab = 1;
结果:
未被捕获的语法错误:无效的或意外的标记
function 1test(){ }
结果:
// Uncaught SyntaxError: Invalid or unexpected token
// 关键字不可赋值
new = 5;
function = 1; // Uncaught SyntaxError: unexpected token= 这里的=是意外的标记
// 基本的语法错误
var a = 5: // Uncaught SyntaxError: unexpected token: 这里的:是不合法的标记
// 2、ReferenceError 引用错误
// 变量或者函数未被声明的时候
test() // Uncaught ReferenceError: test is not defined // 未捕获的引用错误: test没有被定义
console.log(a);
// 给无法被赋值的对象赋值的时候
// var 1 = 2; 语法错误
var a = 1 = 2; // Uncaught SyntaxError: Invalid left-hand side in assignment 赋值左侧是无效的
// 出现这种情况一般是赋值出问题了
var a = 1;
console.log(a); = 1;
// 3、RangeError 范围错误
// 数组长度赋值为负数
var arr = [1, 2, 3];
arr.length = -1;
console.log(arr); // Uncaught RangeError: Invalid array length 无效的数组长度
// 对象方法参数超出可行范围
var num = new Number(66.66);
console.log(num.toFixed(-1));
// Uncaught RangeError: toFixed() digits argument must be between 0 and 100
// 数字参数必须在0~100之间
// 4、TypeError 类型错误
// 调用并不存在的方法
test() // Uncaught ReferenceError: test is not defined 引用错误: test未被定义
123() // Uncaught TypeError: 123 is not a function 类型错误: 123不是一个函数
// 它先检查123是不是函数命名的方式,如果是的话就报引用错误,如果不是的话就报类型错误
var obj = {};
obj.say(); // // Uncaught TypeError: obj.say is not a function
// 如果对象里面没有找到这个方法,JS引擎就会认为这是一个属性,然后这个属性被执行了就是类型错误, 因为属性不是函数一样可以执行,所以是类型错误
// 实例化原始值
var a = new 123;
var a = new ‘string’; // Uncaught TypeError: “string” is not a constructor "string"不是一个构造函数
// 5、URIError URI错误
var myUrl = ‘http://www.baidu.cin?name=艾小野’;
// 把中文字转换成中文编码字符
var newUrl = encodeURI(myUrl);
console.log(newUrl); // http://www.baidu.cin?name=%E8%89%BE%E5%B0%8F%E9%87%8E
// 上面的=%E8%89…是中文字符编码字符
// 一般在URL上面会转化成中文编码字符,这样可读性就少了,但是URL都是外国人发明的东西,所以URL里面出现中文本身是属性意料范围之外的,所以说用encodeURI可以把URL地址里面的中文转化成中文编码字符,有可能是UNICODE/GBK/GB2312/UTF-8,
// 为什么这里不是URL了还可以转化?
var myUrl = ‘艾小野’;
var newUrl = encodeURI(myUrl);
// 因为encodeURI转化的就URI,URI是资源标识,只要是资源标识就可以转换成中文字符编码
// 把中文字符编码转回中文
var myUrl = ‘http://www.baidu.cin?name=%E8%89%BE%E5%B0%8F%E9%87%8E’;
var newUrl = decodeURI(myUrl);
console.log(newUrl);
// 这样乱写一个可以转换吗?为什么?
var str = decodeURI(’%fdsdf%’); //Uncaught URIError: URI malformed 不符合常规的URI
// decodeURI转换的URI都是有规范的,不符合常规的URI的是无法转换的
// 了解
// URI:UNIFORM RESOURCE IDENTIFIER 统一 资源 标志符
// URL:UNIFORM RESOURCE LOCATOR 统一 资源 定位符
// URN:UNIFORM RESOURCE NAME 统一资源名称
// URL:http://www.baidu.com/new#today
// fpt://wwww.baidu.com/ftp#developer
// 访问协议 域名 资源空间 这三个东西都有、或者有前俩,就是URL
// 通过一个地址能够直接访问到一个特定的页面,或执行某一个特定的web程序就是URL
// URN:比如:"wwww.baidu.com/ftp#developer"就是一个URN, 这个东西是代表资源的唯一的标识, 就相当于一个名称或者ID,通过它是无法访问的,但是它指代了一个资源的唯一性唯一的ID/资源访问
// href="tel:1390000000"也是URN,但它不是一个URL,因为它并不指代一个特定的可访问的资源
// href="mailto:237219871@qq.com"也是URN,它指代的是一个资源的名称,你通过它是无法访问的
// 点击了URN之后弹出一个让你写邮件的东西,但这不是它弹出来的,这是程序自执行依靠这个URN这个标识去调用的,而不是它自己去访问的
// URN在手机一点击就能打电话、一点击就可以发邮件,这是手机内部系统去调用的,而不是通过这个地址去访问的
// 6、EvalError eval函数执行错误 (不建议使用eval)
eval(‘var a = 1; console.log(a)’); // 1
// 程序写成字符串放到eval里面是可以执行的
var str = eval(‘1’); console.log(str) // 1
// 为什么eval现在用的少了?
var obj = {
a: 1,
b: 2
}
console.log(eval(‘obj’)); // { a:1, b: 2} 这里是打印obj对象,而不是’obj’
console.log(eval(obj)); // { a:1, b: 2} 这段代码不规范,eval里面应该是字符,但是不放字符串也行
// 综上,这也就是不推荐使用的原因
// 最大的作用:一般后台的时候, 后端跟前端有json数据的对接, 就是从后端获取json数据, 也有可能是从后端直接获取json的字符串数据,然后eval可以把joson字符串数组转换成json对象,然后就可以在JavaScript里面遍历、访问里面的东西
// json和对象有什么区别?
// 对象
var obj = {
‘a’: 1,
‘b’: 2
}
// 对象的属性可以写成字符串的形式
// 可以通过obj[‘a’], obj.a等方式访问属性
// json对象
{
“a”: 1,
“b”: 2
}
// json就是花括号这一块
// json数据一般来说属性都是用双引号, 这和后端转译有关系,后端传回来的json字符串都是用双引号的,所以前端也用双引号,在JavaScript当中json又是一个对象
{
“a”: 1,
“b”: 2
“say”: function() { }
}
// 这就不是json字符串了,因为json字符串和json对象里面是不可以嵌有方法的,所以说这里就是一个普通的对象
// json对象json数据是干嘛用的?
// json数据是存储数据用的
// json字符串是什么?
var jsonData = [
{
“a”: “1”,
“b”: “2”
},
{
“a”: “5”,
“b”: “6”
}
];
// 一般来说从后端传到前端的数据都是这样的,但有些时候是直接传字符串在前端进行处理数据
var jsonData = ‘[’ +
‘{’ +
‘“name”: “abc”’ +
‘},’ +
‘{’ +
‘“name”: “bcd”’ +
‘},’ +
‘{’ +
‘“name”: “bcd”’ +
‘}’ +
‘]’;
console.log(jsonData); //[{“name”: “abc”,},{“name”: “bcd”,},{“name”: “bcd”,}] 三组json数据
// 把上面三组json字符串变成对象
var data = eval(’(’ + jsonData + ‘)’)
console.log(data);
// eval可以很快的把json的字符串数据转换成对象,然后可以通过循环输出它的name
for (var i in data) {
var item = data[i];
console.log(item.name);
}
// 为什么不推荐使用eval了?
// 1.语法规范性不好(加与不加字符串都能执行)
// 2.不好调试
// 3.性能问题(新的方法:json.parse)
// 4.有些时候代码压缩混淆的时候容易出错
// 5.存在安全性问题(容易引起XXX的攻击)
// 6.可读性太差了
// 人为的抛出错误
var error = new Error(‘代码错误了’);
console.log(error); // Error: 代码错误了
var error = new RangeError(‘代码错误了’)
console.log(error); // RangeError 代码错误了
var error = new SyntaxError(‘代码错误了’);
console.log(error); // SyntaxError: 代码错误了
var error = new ReferenceError(‘代码错误了’);
console.log(error); // ReferenceError: 代码错误了
var error = new TypeError(‘代码错误了’);
console.log(error); // ReferenceError: 代码错误了
var error = new EvalError(‘代码错误了’);
console.log(error); // ReferenceError: 代码错误了
var error = new URIError(‘代码错误了’);
console.log(error); // ReferenceError: 代码错误了
// JavaScript有六种错误类型,每一种类型都有对应的构造函数,这些构造函数都可以实例化错误对象,可以自定义错误
// 上面的6种错误是系统自动为我们抛出的错误
// 手动抛出错误的方法
// try catch finally throw (这四个是一组,前两个必写,后两个可不写)
try {
console.log(‘正常执行1’); // ‘正常执行1’
console.log(a); // 这里就不会报错,而是把错误传给catch
console.log(b); // 这里就不会执行了,因为上面已经报错停止了执行
console.log(‘正常执行2’); // ‘正常执行2’
} catch (e) { // 捕获错误
console.log(e); // ReferenceError:a is not defined
console.log(e.name + ‘:’ + e.message); // ReferenceError:a is not defined(e实际上是对象,只是打印出来是字符串)
} finally {
console.log(‘正常执行3’); // ‘正常执行3’
}
console.log(‘正常执行4’); // ‘正常执行4’
// try: 正常执行的时候,没有错误的时候,是不走catch的;
// try不执行了但不影响catch执行,和外部的代码执行,也不会影响finally的执行
// catch: 第一要务就是捕获try里面的错误,它可以捕获具体的错误内容,可以对错误类型进行判断,根据错误类型采取相应的执行方案,这样就多了一种备用方案的可能性
// finally:不管try里面有没有错,finally都执行,所以finally和外部的语句一样,它的意义就是让代码看起来工整一些
// 案例
// jsonStr在等待后端给它重新赋值,给它传一个JSON字符串的东西,然后处理它,用try_catch检查这个JSON字符串有没有传过来
var jsonStr = ‘’;
try {
if (jsonStr == ‘’) {
throw ‘JSON字符串为空’
}
console.log(‘我要执行啦!!!’);
var json = JSON.parse(jsonStr); //JSON.parse可以把JSON字符串转换成JSON对象
console.log(json);
} catch (e) {
console.log(e); // Unexpected end of JSON input JSON.parse里面是不可以给空字符串的,里面必须是一个json字符串
var errorTip = {
name: ‘数据传输失败’, // 换方案执行
errorCode: ‘10010’
}
console.log(errorTip); // JSON字符串为空 { name: “数据传输失败”, errorCode: “10010” }
}
// throw:是抛出错误信息的意义,它可以自定义抛出的错误信息
// ES5严格模式
// ECMAScript JavaScript的语法规范 方法规范
// 97 1.0
// 98 2.0
// 99 3.0 JS通行标准 (到ES5所有的语法基础都是基于3.0的)
// 07 4.0 草案(版本更新太过激进) Mozilla Branden Eich(JS作者)支持
// 08 4.0 中止 把容易改善的部分放到了3.1当中,给激进的部分取了一个版本代号,叫Harmony(和谐)
// 不久后ES3.1更名为ES5
// 09 5.0 ES5发布,Harmony -> 分成两部分: 1.JS.next(激进当中不是那么激进的部分) 2.JS.next.next(比较激进的部分)
// 11 5.1 成为了ISO国际标准
// 13 ES6 = JS.next 把js.next.next 放到了es7里面
// 13 ES6草案发布
// 15 ES6正式发发布,ECMAScript1025
// ES5 正常模式 严格模式
// IE9及一下IE是不支持严格模式的
// 为什么要用严格模式?
// 3.0语法的严谨和合理性有不足的地方,为了让ES3的语法在ES5能够正常运行,使用严格模式就可以按照ES5的语法规范来运行程序
// 声明方法:
// ‘use strict’
// 为什么严格模式要写成字符串?
// 因为如果5.0新出了一个方法,3.0不支持的话就会报错,所以写成字符串就不会影响程序的执行
// 启动严格模式:
// 整个脚本启动:在整个脚本的最上一行写:‘use strict’
// 函数内部启动:
function test() {
‘use strict’
}
var test = (function () {
‘use strict’;
})();
// 这样写就不会影响外部
// with方法
‘use strict’
var a = 1;
var obj = {
a: 2
}
function test() {
var a = 3;
var b = 4;
with (obj) { // Uncaught SyntaxError: Strict mode code may not include a with statement 严格模式的代码是不能包含with的表达式
console.log(a); // 2
console.log(b); // 4 obj里没找到就找自己的
}
}
test()
// with可以改变作用域,with里面填哪个作用域的名称,with的作用域就是哪个
// 原理就是把原型链的最顶端直接指向改变的作用域, 然后就直接在改变的作用域里面找,其次是才从自己的找作用域(和一般的继承查找恰好相反)
// 如果在严格模式下就会报错
// 命名空间:
// 避免一个脚本里面出现同一个名称的变量和函数名,防止命名冲突的情况
// 模块化开发
// var initXXX = (funciton(){…})(); 原生/JQuery写法
window.onload = function () {
init();
}
function init() {
initSideder;
initSideBar;
}
var initSlider = (function () {
var a = 1;
console.log(a);
});
var initSideBar = (function () {
var a = 2;
console.log(a);
})
// 以前的方法
var namespace = {
header: {
Jenny: {
a: 1,
b: 2
},
Ben: {
a: 3,
b: 4
},
sideBar: {
a: 5,
b: 6
}
}
}
// console.log(namespace.header.Ben.a); 比较麻烦
with (namespace.header.Ben) {
console.log(a);
}
// 现在基本上用webpack来写;
// with的缺点:
// with改变作作用域的用域链会消耗很大的性能,所以在性能这方面ES5是不支持的,所以严格模式会报错
// 在严格模式下caller和callee也是不能使用的
// callee:返回实参列表的函数本身
// caller:返回调用它的函数本身
‘use strict’
function test() {
console.log(arguments.callee); // Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them
}
// caller、callee和arguments的属性们在严格模式下不能通过
‘use strict’
function test1() {
test2()
}
function test2() {
console.log(test2.caller); // Uncaught TypeError: ‘caller’, ‘callee’, and ‘arguments’ properties may not be accessed on strict mode functions or the arguments objects for calls to them
}
// caller、callee和arguments的属性们在严格模式下不能通过
// 在严格模式下变量不var声明也会报错
‘use strict’
a = 1; //Uncaught ReferenceError: a is not defined
var a = b = 1; //Uncaught ReferenceError: b is not defined
function test() {
var a = b = 1; //Uncaught ReferenceError: b is not defined
}
test()
// 在严格模式下函数this没有指向
‘use strict’
console.log(this); // window
‘use strict’
function test() {
console.log(this); // undefined
}
test()
// 在函数内部this必须赋值否则就是undefined
‘use strict’
function test() {
console.log(this); // test1
}
var test1 = new Test();
// this执行实例对象
‘use strict’
function test() {
console.log(this); // 1
}
test.call(1) // 给this赋值1,不赋值就是undefined
// 正常模式:
function test() {
console.log(this); // Number {1}
}
test.call(1) // 包装类数字对象,因为call改变是this指向,this指向的一定是对象
// 在严格模式下函数的参数不能重复
// 正常模式:
function test(a, a) {
console.log(a); // 2
}
test(1, 2)
‘use strict’
function test(a, a) {
console.log(a); // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
}
test(1, 2)
// 函数的参数名不能重复
// 在严格模式下对象的属性是不允许重复的
// 下面obj.a打印什么?(面试)
‘use strict’
var obj = {
a: 1,
a: 2
}
console.log(obj.a); // 2(不报错)
// 严格模式下函数参数重复报错,对象属性重复不报错
// 在严格模式下eval有自己独立的作用域
// 正常模式:
eval(‘var a = 1; console.log(a)’) // 1
console.log(a); // 1
‘use strict’
eval(‘var a = 1; console.log(a)’) // 1
console.log(a); // Uncaught ReferenceError: a is not defined