闭包和递归
深拷贝和浅拷贝
首先深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。
浅拷贝:
- for···in只循环第一层
// 只复制第一层的浅拷贝
function simpleCopy(obj1) {
var obj2 = Array.isArray(obj1) ? [] : {};
for (let i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var obj1 = {
a: 1,
b: 2,
c: {
d: 3
}
}
var obj2 = simpleCopy(obj1);
obj2.a = 3;
obj2.c.d = 4;
alert(obj1.a); // 1
alert(obj2.a); // 3
alert(obj1.c.d); // 4
alert(obj2.c.d); // 4
- 简单的赋值 =
深拷贝:
-
采用递归去拷贝所有层级属性
function deepClone(obj){ let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(key in obj){ if(obj.hasOwnProperty(key)){ //判断ojb子元素是否为对象,如果是,递归复制 if(obj[key]&&typeof obj[key] ==="object"){ objClone[key] = deepClone(obj[key]); }else{ //如果不是,简单复制 objClone[key] = obj[key]; } } } } return objClone; }
let a=[1,2,3,4], b=deepClone(a); a[0]=2; console.log(a,b); -
通过JSON对象来实现深拷贝
function deepClone2(obj) { var _obj = JSON.stringify(obj), objClone = JSON.parse(_obj); return objClone; }
对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。同时如果对象中存在循环引用的情况也无法正确处理。
-
通过jQuery的extend方法实现深拷贝
var array = [1,2,3,4]; var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
-
手动实现深拷贝
let obj1 = { a: 1, b: 2 } let obj2 = { a: obj1.a, b: obj1.b } obj2.a = 3; alert(obj1.a); // 1 alert(obj2.a); // 3
-
直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i]; // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况 if(prop === obj) {
continue; }
if (typeof prop === 'object') { obj[i] = (prop.constructor === Array) ? [] : Object.create(prop); } else { obj[i] = prop; } }
return obj; } -
lodash函数库实现深拷贝
let result = _.cloneDeep(test) Reflect法 // 代理法 function deepClone(obj) { if (!isObject(obj)) { throw new Error('obj 不是一个对象!') }
let isArray = Array.isArray(obj) let cloneObj = isArray ? [...obj] : { ...obj } Reflect.ownKeys(cloneObj).forEach(key => { cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key] }) return cloneObj
}
深浅拷贝都可:
- Object.assigns
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
如果对象的属性值为简单类型(如string, number),通过Object.assign({},srcObj);得到的新对象为深拷贝;如果属性值为对象或其它引用类型,那对于这个对象而言其实是浅拷贝的。
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({}, obj); // obj赋值给一个空{}
obj1.a = 3;
console.log(obj.a);// 1
var obj = {
a: { f: 1 }
}
var obj1 = Object.assign({}, obj); // obj赋值给一个空{}
obj1.a.f = 3;
console.log(obj.a.f);// 3
-
concat和slice
// 当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝 var arr1 = ["1","2","3"]; var arr2 = arr1.concat(); // var arr2 = arr1.slice(0); arr2[1] = "9"; console.log("数组的原始值:" + arr1 ); // 1,2,3 console.log("数组的新值:" + arr2 ); // 1,9,3 // 当数组里面的值是引用数据类型,比如Object,Array时,属于浅拷贝 var arr1 = [{a:1},{b:2},{c:3}]; var arr2 = arr1.concat(); arr2[0].a = "9"; console.log("数组的原始值:" + arr1[0].a ); // 数组的原始值:9 console.log("数组的新值:" + arr2[0].a ); // 数组的新值:9
-
扩展运算符
// 当value是基本数据类型,比如String,Number,Boolean时,是可以使用拓展运算符进行深拷贝的 // 当value是引用类型的值,比如Object,Array,引用类型进行深拷贝也只是拷贝了引用地址,所以属于浅拷贝 var car = {brand: "BMW", price: "380000", length: "5米"} var car1 = { ...car, price: "500000" } console.log(car1); // { brand: "BMW", price: "500000", length: "5米" } console.log(car); // { brand: "BMW", price: "380000", length: "5米" }
call、apply和bind
apply()和 call():
这两个方法都是在特定的作用域中调用函数,实际上等于设置函数体内 this 对象的值。并立即执行这个函数。
apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组
call()方法接收两个参数:一个是在其中运行函数的作用域,传递给函数的参数必须逐个列举出来
使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。
bind():
bind方法生成了一个新的函数,称为绑定函数,传入bind方法的第一个参数作为这个绑定函数的this对象,传入bind的第二个参数连同后面调用绑定函数时传入的参数按照先后顺序(传入bind的在前)构成绑定函数的参数。
bind方法可以让对应的函数想什么时候调就什么时候调用,并且可以将参数在执行的时候添加。
This
this对象是在运行时基于函数的执行环境绑定的:
- 在全局函数中,this等于 window
- 当函数被作为某个对象的方法调用时,this等于那个对象。
- 匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window。
cookies,sessionStorage 和 localStorage 的区别?
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),即会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有期时间:
localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage 数据在当前浏览器窗口关闭后自动删除。
get和post
- GET - 从指定的资源请求数据。POST - 向指定的资源提交要被处理的数据。
- GET 请求可被缓存,POST 请求不会被缓存
- GET后退不会有影响,POST 后退会重新进行提交
- GET 请求保留在浏览器历史记录中,POST 请求不会保留在浏览器历史记录中
- GET 请求可被收藏为书签,POST 不能被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET 请求有长度限制 URL 的最大长度是2048个字符,POST 请求对数据长度没有要求
- GET 请求只应当用于取回数据