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();
原文地址:https://www.cnblogs.com/styleFeng/p/14314634.html