一、JavaScript异常处理
1、Error异常
代码运行过程中出现错误,异常不是语法错误。
2、代码Error异常处理
<script>
try{
// 可能出现异常的代码
}catch(e){
// 出现异常的代码会存储到e这个变量中,这个e也是异常对象,然后执行catch中的代码,
// 如果没有异常,会执行try中的代码,不会执行catch花括号的代码
}
// try catch 不能处理语法错误的代码
// 异常会向上传递,调用了有异常的代码,那么这个调用的函数也会出现异常。(与变量会向上查找一样,当前作用域没有这个变量,会向这个作用域的上一级作用域查找此变量,知道查找到全局为止)
function fn1(){
fn2()
console.log(1)
}
function fn2(){
console.log(2) // 2
fn3()
console.log(3)
}
function fn3(){
// try{
// a.fn4()
// }catch(e){
// console.log(e);
// }
a.fn4()
console.log(4)
}
fn1();
// 如果代码出现异常,代码就不会向下执行,使用try catch语法,可以大概检测到哪里代码出现了异常,可以继续执行后面的代码。
</script>
3、 抛出异常 throw
<script>
console.log(2);
try{
// throw 语句允许用户创建自定义错误
var error1 = new Error('error message');
// 抛出异常
throw error1;
}catch(e){
console.log(e)
console.log(error1)
console.log(e.name);
console.log(error1.name);
console.log(e.message);
console.log(error1.message);
console.log(e.toString());
console.log(error1.toString());
console.log(error1 === e);
}
console.log(1);
</script>
二、JavaScript中的DOM对象和类型
1、 DOM对象
//DOM 文档对象模型 HTML文档中每个(元素标签)节点,就是DOM对象(标签、文本、注释),HTML文档就是一个节点树
2、类型
javascript中一共有六种主要类型
- string
- number
- boolean
- null
- undefined
- object
简单基本类型(值类型)(string、number、boolean、null、undefined)本身并不是对象,null有时候会当做一种对象类型,但这其实只是语言本身的一个bug,即对null执行typeof null 时返回字符串"object",(注:原理是这样的,不同的对象在底层都表示二进制,在javascript中二进制前三位都为0的话,会判断为object类型,null的二进制表示是全为 0 ,自然前三位也是0,所以执行typeof null时会返回 object)实际上null本身是基本类型
有一种常见的错误说法,就是 javascript中万物皆对象,这显然是错误的。
除了简单类型,还有复杂类型(引用类型) (函数(function)、object、数组(Array))
值类型的值存储在栈空间中,值类型传递的时候传递的是值。
引用类型对象的地址(引用)存储在栈空间中,对象存储在堆空间中,引用类型传递的时候传递的是地址(引用)。
值类型
引用类型
内置对象
- String
- Number
- Bollean
- Object
- Function
- Array
- Data
- RegExp
- Error
3、问题解答
以下代码为什么交换位置结果不一样呢?
4、值类型和引用类型作为函数参数处理
-
函数里面的相关术语
- 形参(形式参数):占位用的参数,用来接收数据的参数而已,在没有调用函数的时候形参是没有值的。
- 实参(实际参数):实际传递的参数。
- 函数的调用:在函数被调用的时候,函数会默认把实参的值赋值给形参
-
值类型作为函数的参数:在函数内部对形参变量进行修改是不会影响到实参的值。因为实参和形参他们的数据是相互独立的。
-
引用类型作为函数的参数:在函数内部对形参变量进行修改会影响到实参的值,因为他们的引用指向同一个对象。(形参和实参共享同一份数据,修改其中的某个对象对另外一个对象也会有影响)
<script>
//01 值类型作为函数的参数传递
var number = 10;
function funcName(n) {
//n = number; 内部默认的实现
n = 5;
console.log(n); //number = 5
}
funcName(number); // 将 number 拷贝出来给 funcName函数中 n 变量
console.log(number); //10
// funcName函数中的形参变量无论怎样更改,函数外面的 number 变量都不受任何影响
</script>
<script>
//02 引用类型作为函数的参数传递
var obj = {name:"小明"};
console.log(obj.name);//小明
function funcName(param) {
param.name = "小王";
param = {
name:"小红"
};
console.log(param.name); //小红
}
funcName(obj);
console.log(obj.name); //小王
</script>
画图说明 引用类型传参
var arr1 = [1,2,3];
var arr2 = arr1;
console.log(arr1); // [1, 2, 3]
console.log(arr2); // [1, 2, 3]
arr2 = [4,5,6]; //该行代码切断和arr1的关系,对象内保存的地址指向了另外一块内存空间
arr1.push(4);
console.log(arr1); //1,2,3,4
console.log(arr2); //4,5,6
// 之前的对象赋值给一个新的对象,拷贝的是之前对象的引用,
三、深拷贝和浅拷贝
1、深拷贝和浅拷贝
拷贝:也叫复制,就是把当前的目标复制一份,存放在另一个地方
值类型
var a = 10;
var b = a;
// 值类型中拷贝就是将变量复制一份, 存放到另一块内存中,也就是说内存中有两个10,这是拷贝
引用类型
var arr1 = [1,2,3];
var arr2 = arr1;
// 引用类型 中就是不是拷贝,而是变量的引用发生了改变,两个变量地址,指向同一个数据对象。(数据有一份)
浅拷贝
浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响。
// 浅拷贝只是拷贝当前对象,而不拷贝对象中引用的其他对象
function clone(obj){
var o = {};
for(var k in obj){
o[k] = obj[k];
}
return o;
}
var p = {
name:'夏明',
book:{
name:'js基础'
}
}
var p1 = clone(p);
console.log(p.name) // 夏明
console.log(p.book.name) // js基础
console.log(p1.name) // 夏明
console.log(p1.book.name) // js基础
p1.name = '小红';
p1.book.name = "js高级";
console.log(p.name) //夏明
console.log(p.book.name) // js高级
console.log(p1.name) // 小红
console.log(p1.book.name) // js高级
深拷贝
深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复制的对象的引用不包含任何原有对象或对象上的任何对象,复制后的对象与原来的对象是完全隔离的。
//深拷贝 就是将所有的对象全部拷贝,在内存中拷贝的对象是独立存在的
function deepClone(obj){
var o = {};
for(var k in obj){
if(typeof obj[k]=='object'){
o[k] = deepClone(obj[k]); // 如果是引用类型在拷贝一次
}else{
o[k] = obj[k]; // 基本类型拷贝一次
}
}
return o;
}
var p = {
name:'夏明',
book:{
name:'js基础'
}
}
var p1 = deepClone(p);
console.log(p.name)
console.log(p.book.name)
console.log(p1.name)
console.log(p1.book.name)
p1.name = '小红';
p1.book.name = "js高级";
console.log(p.name)
console.log(p.book.name)
console.log(p1.name)
console.log(p1.book.name)
深拷贝
学IT,上博学谷