• js 深浅拷贝+call/apply/bind


    一、传值与传址

    基本类型的值存在栈内存中

    引用类型的地址存在栈内存中,地址指向堆内存中存储的值

    浅拷贝和深拷贝是针对引用类型的数据来说的。

    二、浅拷贝

    把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用。
    //浅拷贝(数组)
        function arrExtend(arr){
          let a = [...arr]
          let b = [].concat(arr)
          let c = arr.slice()
        }
    
        function objExtend(obj){
          let a = Object.assign({}, obj)
        }
    
    
        //浅拷贝(对象)
        function type(obj){
          return Object.prototype.toString.call(obj).slice(8,-1)
        }
    
        //浅拷贝(对象和数组 -- 不拷贝原型)
        function easyExtend(obj){
          let result = null
          if(type(obj) === "Object"){
            result = new Object()
          }else if(type(obj) === "Array"){
            result = new Array()
          }
    
          for(let key in obj){
            if(obj.hasOwnProperty(key)){
              result[key] = obj[key]
            }
          }
    
          return result
        }

    三、深拷贝

    把一个对象中所有的属性或者方法,一个一个的找到.并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中。
     
    //深拷贝(不拷贝原型)
        function type(obj){
          return Object.prototype.toString.call(obj).slice(8,-1)
        }
        function deepExtend(obj){
          let result
          if(type(obj) === "Object"){
            result = new Object()
          }else if(type(obj) === "Array"){
            result = new Array()
          }
    
          for(let key in obj){
            if(obj.hasOwnProperty(key)){
              if(typeof obj[key] === "object"){
                if(obj[key] === null){
                  result[key] = null
                }else{
                  result[key] = deepExtend(obj[key])
                }
              }else{
                result[key] = obj[key]
              }
            }
          }
          return result
        }
    
        //深拷贝
        JSON.stringify()
        JSON.parse()
        //通过 JSON.parse(JSON.stringify(obj)) 可产生一个新对象

    四、call-apply-bind

    call:可以改变函数指向,第一个参数是要改变指向的对象,之后的参数形式是 arg1, arg2... 的形式

    apply:用法基本同 call一样,不同点在于第二个参数是一个数组 [arg1, arg2...]

    bind:改变 this 作用域会返回一个新的函数,这个函数不会马上执行

    apply的使用语法
    函数名字.apply(对象,[参数1,参数2,...])
    方法名字.apply(对象,[参数1,参数2,...])
     
    call的使用语法
    函数名字.call(对象,参数1,参数2,...)
    方法名字.call(对象,参数1,参数2,...)
     
    bind的使用语法
    函数名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个函数
    方法名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个方法
     
    call/apply
    function Person(age) {
      this.age = age;
    }
    Person.prototype.sayHi = function (x, y) {
      console.log((x + y) + ":====>" + this.age);//是实例对象
    };
    
    function Student(age) {
      this.age = age;
    }
    var per = new Person(10);//实例对象
    var stu = new Student(100);//实例对象
    //sayHi方法是per实例对象的
    per.sayHi.apply(stu, [10, 20]);
    per.sayHi.call(stu, 10, 20);

    bind

    function Person(age) {
      this.age=age;
    }
    Person.prototype.play=function () {
      console.log(this+"====>"+this.age);
    };
    
    function Student(age) {
      this.age=age;
    }
    var per=new Person(10);
    var stu=new Student(20);
    //复制了一份
    var ff=per.play.bind(stu);
    ff();

    function ShowRandom() {
    this.number=parseInt(Math.random()*10+1); } //添加原型方法 ShowRandom.prototype.show1=function () { //改变了定时器中的this的指向了,本来应该是window,现在是实例对象了 window.setInterval(this.show2.bind(this),1000); }; ShowRandom.prototype.show2=function () { console.log(this.number); }; //实例对象 var sr=new ShowRandom(); sr.show1();
  • 相关阅读:
    爬楼梯 C++
    买卖股票的最佳时机 C++
    删除排序数组中的重复数字 Java
    软件工程第一次作业
    Deep Learning Overview
    SSE优化在数学库中的应用之一
    Windbg调试符号概括
    SSE优化在数学库中的应用之二
    Windbg初探
    vector与hashTable结合提升数据操作能力(空间不为瓶颈)
  • 原文地址:https://www.cnblogs.com/styleFeng/p/14314634.html
Copyright © 2020-2023  润新知