ES6-11 总结三(深浅拷贝,对象和函数的扩展)

ES6-11 总结一 (nrm,var,let,const,解构赋值) : https://www.jianshu.com/p/b04fbab076b3
ES6-11 总结二 (ES5和ES6数组的 遍历&扩展) : https://www.jianshu.com/p/a775c3311a0b
ES6-11 总结三(深浅拷贝,对象和函数的扩展) : https://www.jianshu.com/p/6dda93b18d9a
ES6-11 总结四 (es5和es6的类与继承,Symbol数据类型) : https://www.jianshu.com/p/e3c24c0db755
ES6-11 总结五 (set,Map,字符串&&正则&&数值的扩展) : https://www.jianshu.com/p/c1ca903f6573
ES6-11 总结六 (代理Proxy 反射Reflect):https://www.jianshu.com/p/4ff19ba5d219

1 函数

1.1 函数的参数

// 参数默认值
function Fn (x,y="world"){
  console.log(x,y)   // Hello world
}
Fn("Hello")

// 函数的参数,是默认被声明的
function Fn (x){
  let x =5  
}
Fn()  // 报错!..x已经被声明了,,不允许再次声明

// 函数参数不能试重复的
function Fn (x,x,y){
  let x =5  
} //  报错!

// 解构赋值传参,两边结构要一致
function Fn ({x,y}){
}
Fn ({}) //  不能Fn()会报错
image.png

1.2 函数的length

// length 会返回没有默认值的参数个数
function Fn (x,y,z){}
Fn.length //3

function Fn (x,y,z=1){}
Fn.length //2

1.3 函数的作用域

image.png
作用域链是往外找,,不是往里找,
image.png

1.4 函数的name属性

function foo(){}    foo.name //  foo

(new Function).name  // anonymous   匿名的意思

foo.bind({}).name   //  bound foo,,,用了bind会多一个bound

(function(){}).bind({}).name  // bound
bind回忆
image.png

2 ...的两种含义: 扩展运算符和rest参数

2.1 ... 扩展运算符

function foo (a,b,c){
  console.log(a,b,c)
}
let arr = [1,2,3]
foo (...arr) // 1 2 3

2.1.1 用扩展运算符合并数组

let arr1 = [1,2,3]
let arr2 = [4,5,6]

// es5 做法
Array.prototype.push.apply(arr1,arr2)

// es6 做法
arr1.push(...arr2)

2.1.2 用扩展运算符让字符串变成数组

let str = "abc"

let arr = [...str]  // [a,b,c]

2.2 ...的rest参数

2.1.1 不定参数求和,,,
下图注释的为es5写法 结果都为3,6
image.png
下图注释的为es6写法 结果都为3,6
image.png
...的rest参数作用于解构赋值
image.png
总结 : ...出现在=左边或者是形参那么是rest参数,,------,如果在=右边,或者是实参,就是扩展运算符

2 箭头函数

// es5声明函数的两种方式和区别
1  function fn(){}
2  let fn = function(){}

//区别:  
//fn可以在1的前面调用,,,但是不能在2的前面调用..,,因为1函数有预定义

// es6 箭头函数
let fn = (x,y) =>{}

this指向问题 : 是定义时的this,.而不是调用的this,,也是箭头函数外层的this
箭头函数不能作为构造函数,也就是不能new fn
箭头函数沒有arguments    但是可以使用...来接收
例如 let fn = (...XX) =>{  XX就等同于arguments  }

3 对象的扩展

3.1 对象的简易赋值, 如果b的key和value 名字是一样的,,可以简写一个a,
let a =1
let b ={
  a,
}


3.2 让对象的key变成一个变量,,对象的key,跟这a变动
//例如
let a= "xx"
let b= {
  [b] : "刘"
}
console.log(b)  // {xx: "刘"}   


3.3 对象里面不应该使用箭头函数,,应该使用fn2这种es6简写方式
let obj ={
  age : 18,
  fn : ()=>{
      console.log(this.age) 
  }
  fn2(){
      console.log(this.age) 
  }
}
obj .fn() // 会报错,,因为此时箭头函数指向的不是obj,,,是window,
obj .fn2()  // 就可以拿到age


3.4 遍历对象的属性
let obj = {a:1, b:2}

1 for in  遍历
for(let key in obj){ 
  console.log(key,obj[key])    
  //打印结果
  // a 1
  // b 2
}

2 Object.keys  遍历
Object.keys(obj).forEach((key)=>{  
  console.log(key,obj[key])  
  //打印结果
  // a 1
  // b 2
})

3 Object.getOwnPropertyNames  遍历,,用法类似于Object.keys
4 Reflect.ownKeys   遍历   用法类似于Object.keys


3.5 Object.is 方法   判断两个是否相等
Object.is(2,2)   // true

Object.is(2,"2")  // false

Object.is(+0,-0)  // false

Object.is(NaN,NaN) // true


3.6 Object.assign合并对象
Object.assign(目标对象,被合并对象)类似于es6...扩展运算符


3.7 es6  in
判断对象里面是否包某个属性
let a = { b : 1 ,  c :  2}
"b" in a  // true     
1 in a // false

判断数组里是否包含某个下标是否有值
let arr = [1,2,3]
1 in arr // true
3 in arr // false   判断的是3下标有没有值

4 深拷贝和浅拷贝

Object.assign复制对象出现的问题,
let a = {
    b : {
        c : 1,
        d : 2
    }
};

let b = {
    b : {
        c : 1
    }
};
Object.assign(a,b)
console.log(a);
打印结果为 : {
    b : {
        c : 1
    }
}  
a 的属性d,,,在合并之后丢失了,因为Object.assign只可以直接替换对象里面的基本数据类型,,
遇到引用数据类型,,,只是把地址引过去,,所有有些属性会丢失,,因此是浅拷贝
1   json.stringify和json.parse 可以实现深拷贝,,,,但是太多层嵌套不行
里面也有很多问题,,具体可以参考  https://blog.csdn.net/u013565133/article/details/102819929

2  自己封装一个深拷贝   不考虑函数,,只考虑里面有对象和数组
// 判断是什么类型
let checkType = (data) => {
    let type = Object.prototype.toString.call(data);  // [Object object]  [Object Array]
    type = type.slice(8, -1);
    return type;
};
let deepClone = (target) => {
    let type = checkType(target);
    let result;
    if(type === 'Object'){
        result = {};
    } else if(type === 'Array'){
        result = [];
    } else{
        // 如果是基本数据类型,,直接返回去
        return target;
    }
    for(let targetKey in target){
        let value = target[targetKey];
        let valueType = checkType(value);
        if(valueType === 'Object' || valueType === 'Array'){
            result[targetKey] = deepClone(value);   //递归再次调用
        } else{
            result[targetKey] = value;
        }
    }
    return result;
};

你可能感兴趣的:(ES6-11 总结三(深浅拷贝,对象和函数的扩展))