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();