2020.12.2
01.this指向
事件函数中:指向事件源
普通函数中:指向的是window对象
构造函数中:指向的是实例对象
普通对象中:指向的是当前对象
事件函数中
<body>
<button id="btn">按钮</button>
<script>
btn.onclick=function(){
console.log(this);//指向btn
}
</script>
</body>
普通函数中
function add(){
console.log(this);//指向window
}
add();
构造函数中
function Product(){
this.buy=function(){
console.log(this);//指向Product
}
}
var p=new Product();
p.buy();
普通对象中
var stu={
name:'zs',
eat:function(){
console.log(this);//指向stu
}
}
stu.eat();
02.call、apply、bind
call apply和bind都可以用来修改this指向。只是使用方式不一样
var stu={
name:'zs',
age:12,
weight:200
}
function add(a,b){
console.log(a,b,this.age);
}
//fn.call(所要指向的对象,参数1,参数2,...) 调用fn函数并修改this指向
add.call(stu,1,2);
// fn.apply(所要指向的对象,[参数1,参数2,...]) 调用fn函数并修改this指向
add.apply(stu,[1,2]);
//bind不会直接调用函数,而会返回一个新的函数,返回的新函数修改了this指向
var fn=add.bind(stu,1,2);
fn();
03.变量在内存中的存储
基本数据类型:在内存中以值的形式存在。 字符串、数值、布尔类型、null、undefined
复合数据类型:在内存中以地址的形式存在。 对象
var a=10;
var b=a;
a=100;
//a只会把值赋给b,修改a不影响b的值
console.log(b);//输出10
var stu={
name:'zs'
}
var stu1=stu;
stu.name='ls';
//stu的地址赋给stu1,stu和stu1的地址都指向同一个数据,修改任意一个全部数据都会改变
console.log(stu1.name);//输出ls
04.浅拷贝
浅拷贝:直接把对象的属性一一赋值,不考虑属性值类型
var stu={
name:'zs',
age:14,
hobby:['唱歌','跳舞'],
score:{
math:89,
english:100
}
}
//浅拷贝
var stu1={};
stu1.name=stu.name;
stu1.age=stu.age;
stu1.hobby=stu.hobby;
stu1.score=stu.score;
//浅拷贝后,如果属性值为对象的时候,只要修改一个,其余对象对应数据都会改变
stu.hobby[0]="弹吉他";//stu和stu1的hobby:["弹吉他",'跳舞']
//快速实现浅拷贝
var stu2={};
for(var i in stu){
stu2[i]=stu[i];
}
05.深拷贝
深拷贝:如果对象的属性值为基本数据类型,直接拷贝。如果对象属性对应的值对象,需要解析对象,再去拷贝
var stu={
name:'zs',
age:14,
hobby:['唱歌','跳舞'],
score:{
math:89,
english:100,
lizong:[100,100,200]
}
}
//深拷贝
var stu1={}
stu1.name=stu.name;
stu1.age=stu.age;
stu1.hobby=[];
stu1.hobby[0]=stu.hobby[0];
stu1.hobby[1]=stu.hobby[1];
stu1.score={};
stu1.score.math=stu.score.math;
stu1.score.english=stu.score.english;
// 快速实现深拷贝(函数递归调用)
function deepCopy(obj){
//先判断obj是数组还是对象
if(obj instanceof Array){
var newobj=[];
}else if(obj instanceof Object){
var newobj={};
}
//遍历obj
for(var i in obj){
//如果当前遍历的属性的是对象
if(obj[i] instanceof Object){
//将当前属性作为参数再次调用deepCopy
newobj[i]=deepCopy(obj[i]);//递归
}else{
//如果是基本数据类型直接赋值
newobj[i]=obj[i];
}
}
//返回深拷贝出的新对象
return newobj;
}
var stu1=deepCopy(stu);
stu1.score.math='不及格';//此时修改数据不会全部修改
console.log(stu);
console.log(stu1);
06.高阶函数
函数作为函数的实参
function add(time,color){
setTimeout(function(){
color();
},time);
}
add(1000,function(){
txt.style.color='red';
});
07.闭包
闭包:函数嵌套
功能(2种作用独立):
1.扩大了变量的作用域
2.缩小变量的作用域,防止变量污染
//扩大了变量的作用域
function fn(){
//函数add就是闭包
// 正常情况下 add的作用范围是fn内部
//通过return将add的作用范围扩大到fn外,即可在外面操作add内的变量
return function add(x,y){
console.log(x+y);
}
}
var fn1=fn();
fn1(1,2);//3
//缩小变量的作用域,防止变量污染
(function(){
//放置的是一段有特殊功能的代码
var m=10;
})();
// 自调用函数 ;( function(){})(); 前后都需要有;
console.log(m);//10
08.闭包应用
1.遍历添加事件
<body>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<button>按钮</button>
<script>
var btns=document.getElementsByTagName('button');
for(var i=0;i<btns.length;i++){
/*btns[i].οnclick=function(){
// i是全局变量,点击的时候i的值已经是btns.length;
btn[i].style.background='lime';
}*/
//通过闭包改进(缩小了i的作用域)
(function(i){
btns[i].onclick=function(){
btns[i].style.background='lime';
}
})(i);
}
</script>
2.计时器
//计数器
// 1、可以在函数的外部访问到函数内部的局部变量
// 2、让这些变量始终保存在内存中,不会随着函数的结束而自动销毁
var add=(function(){
var count=0;
return function(){
return count+=1;
}
})();
console.log(add());//1
console.log(add());//2
console.log(add());//3
console.log(add());//4