JS高级三

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
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 像素格子 设计师:CSDN官方博客 返回首页