对象的深拷贝实现原理: 定义一个新的对象,遍历源对象的属性 并 赋给新对象的属性
闭包:子函数能被外部调用到,则该作用连上的所有变量都会被保存下来。
Undefined 其实就是已声明未赋值的变量输出的结果
null 其实就是一个不存在的对象的结果
null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象,所以用typeof检测会返回”object”。
作用域:
1.a =10;//去掉了var 就变成定义了全局变量了 (有待考证)
2,局部变量的优先级要高于同名的全局变量,也就是说当局部变量与全局变量重名时,局部变量会覆盖全局变量
基本类型
对于基本类型,除 null 以外,均可以返回正确的结果。
对于引用类型,除 function 以外,一律返回 object 类型。
基本类型:String、Number、Boolean、Undefined、Null
判断类型
typeof ''; // string 有效
引用类型:Object Function 、Array、
判断引用类型 instanceof 检测的是原型
[] instanceof Array; // true
扩展
typeof ''; // string 有效
typeof 1; // number 有效
typeof Symbol(); // symbol 有效
typeof true; //boolean 有效
typeof undefined; //undefined 有效
typeof null; //object 无效
typeof [] ; //object 无效
typeof new Function(); // function 有效
typeof new Date(); //object 无效
typeof new RegExp(); //object 无效
01浅拷贝
有时候我们只是想备份数组,但是只是简单让它赋给一个变量,改变其中一个,另外一个就紧跟着改变,但很多时候这不是我们想要的
vararr = [1, 2, 3, '4'];vararr2 = arr;
arr2[1] = "test";
console.log(arr); // [1, "test", 3, "4"]console.log(arr2);// [1, "test", 3, "4"]
02 深拷贝
1)数组
对于数组我们可以使用slice() 和 concat() 方法来解决上面的问题
slice
vararr = ['a', 'b', 'c'];vararrCopy = arr.slice(0);
arrCopy[0] = 'test'console.log(arr); // ["a", "b", "c"]console.log(arrCopy);// ["test", "b", "c"]
concat
vararr = ['a', 'b', 'c'];vararrCopy = arr.concat();
arrCopy[0] = 'test'console.log(arr); // ["a", "b", "c"]console.log(arrCopy);// ["test", "b", "c"]
知识点补充:
arrayObj.slice(start, [end]) 该方法返回一个 Array 对象,其中包含了 arrayObj 的指定部分。不会改变原数组
arrayObj.concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
其实也就是下面这么个意思。。。但还是用上面的方法来实现比较简单高效些
function deepCopy(arr1, arr2) {
for(vari = 0; i < arr1.length; ++i) {
arr2[i] = arr1[i];
}
}
(2)对象
对象的深拷贝实现原理: 定义一个新的对象,遍历源对象的属性 并 赋给新对象的属性
varobj = {
name:'Hanna Ding',
age: 22}varobj2 =new Object();
obj2.name = obj.name;
obj2.age = obj.age
obj.name = 'xiaoDing';
console.log(obj); //Object {name: "xiaoDing", age: 22}console.log(obj2);//Object {name: "Hanna Ding", age: 22}
varobj = {
name: 'Hanna',
age: 22}vardeepCopy =function (source) {
varresult = {};
for(varkeyin source) {
if(typeofsource[key] === 'object') {
result[key] = deepCopy(source[key])
} else {
result[key] = source[key]
}
}
return result;
}varobjCopy = deepCopy(obj)
obj.name = 'ding';
console.log(obj);//Object {name: "ding", age: 22}console.log(objCopy);//Object {name: "Hanna", age: 22}
一、变量提升
在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域。变量提升即将变量声明提升到它所在作用域的最开始的部分。上个简历的例子如:
console.log(global); // undefined
var global = 'global';
console.log(global); // global
function fn () {
console.log(a); // undefined
var a = 'aaa';
console.log(a); // aaa
}
fn();
之所以会是以上的打印结果,是由于js的变量提升,实际上上面的代码是按照以下来执行的:
var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global
function fn () {
var a; // 变量提升,函数作用域范围内
console.log(a);
a = 'aaa';
console.log(a);
}
fn();
二、函数提升
js中创建函数有两种方式:函数声明式和函数字面量式。只有函数声明才存在函数提升!如:
console.log(f1); // function f1() {}
console.log(f2); // undefined
function f1() {}
var f2 = function() {}
只所以会有以上的打印结果,是由于js中的函数提升导致代码实际上是按照以下来执行的:
function f1() {} // 函数提升,整个代码块提升到文件的最开始<br> console.log(f1);
console.log(f2);
var f2 = function() {}
结语:基本上就是这样,要熟练掌握的话可以多做些练习,test:
console.log(f1());
console.log(f2);
function f1() {console.log('aa')}
var f2 = function() {}
(function() {
console.log(a);
a = 'aaa';
var a = 'bbb';
console.log(a);
})();