1.JS防抖节流
函数防抖 :触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次触发,则重新计算时间
函数节流:高频事件触发,但在n秒内只会执行一次,所以节流 会稀释函数的执行频率
节流案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>按钮</button>
<script>
/*
一间房子只能睡一个人
1:进入房间,默认门是开着的(flag = true),可以直接进来睡觉
2:为了确保安全,需要将门关上(flag = false)
3:睡觉结束(一个事件完成) 需要离开 让下一个进来睡觉 将门打开(flag = true)
如此反复,确保在睡觉这个事件上,一次只能睡一个人
*/
var btn = document.querySelector('button');
var flag = true;
var timer;
btn.onclick = function(){
// 定时器可以写在if里面,也可以写在外面 如果写在外面 必须清除定时器 否则会创建多个定时器 导致flag很快为true
// 如果写在里面 想要执行定时器 必须通过if语句 确保定时器安全
clearTimeout(timer)
if(flag == true){
flag = false;
}
timer = setTimeout(function(){
flag = true
},2000)
}
/*
函数节流:高频事件触发,但在n秒内只会执行一次,所以节流 会稀释函数的执行频率
*/
</script>
</body>
</html>
防抖案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div style="height:5000px; background-color:yellow"></div>
<script>
/*
函数防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次触发
则重新计算时间
*/
function debounce(fn,delay){
var timer = null;
return function(e){
// 清除定时器
clearTimeout(timer)
// 创建一个新的定时器 这样可以保证n秒内 如果再次触发 就不会执行fn函数
timer = setTimeout(()=>{
fn.apply(this,arguments)
},delay)
}
}
// 处理函数
function handle(){
console.log('防抖',Math.random())
}
// 滚动事件
window.addEventListener('scroll',debounce(handle,500))
</script>
</body>
</html>
2.对象创建
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/*
构造函数:其实也是函数,只不过构造函数一般用于和new搭配使用,创建对象
内置构造函数 Object 创建对象
*/
// let obj = new Object();
// // 添加属性和方法
// obj.name = '李四';
// obj.age = 18;
// obj.fn = function(){
// console.log('吃');
// }
// console.log(obj);
// let obj = new Object({name:'张三',age:23,sex:'女'});
// console.log(obj);
// // 如果不需要参数,可以省略小括号
let obj = new Object;
obj.name = '李四';
console.log(obj)
/*
new Array()
new RegExp()
*/
</script>
</body>
</html>
3.静态成员和实例成员
实例成员:实例成员就是构造函数内部通过this添加的成员 name,age,sing就是实例成员
实例成员只能通过实例化对象来访问
静态成员:在构造函数本身上添加的成员 sex就是静态成员
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 自定义构造函数
// 构造函数里面的属性和方法称为成员 成员可以添加
function Star(name,age){
this.name = name;
this.age = age;
this.sing = function(){
console.log('我会唱歌')
}
}
var s = new Star('小写',23);
// 通过new 创建对象 ------实例化对象
// 1:实例成员就是构造函数内部通过this添加的成员 name,age,sing就是实例成员
// 实例成员只能通过实例化对象来访问
console.log(s.name);
// console.log(Star.name); 不能通过构造函数来访问实例成员
// 2.静态成员 在构造函数本身上添加的成员 sex就是静态成员
Star.sex = '男';
// 静态成员只能通过构造函数来访问
console.log(Star.sex);
// console.log(s.sex); undefined
</script>
</body>
</html>
4.构造函数存在的问题
构造函数方法存在浪费内存的问题;
我们希望所有的对象使用同一个函数,这样就节省内存,如何使用同一个函数呢?
5.原型
js规定,每一个构造函数都有一个prototype属性,指向另一个对象;
这个prototype就是一个对象,这个对象的属性和方法,都会被构造函数所拥有;
实例对象可以访问原型中的成员
我们可以把那些不变的方法,定义在prototype对象上,这样所有对象的实例就可以共享这些方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
/* 构造函数存在的问题 浪费内存 */
function Star(name,age){
this.name = name;
this.age = age;
}
// 通过原型来创建函数
Star.prototype.sing = function(){
console.log('我会唱歌');
}
var s1 = new Star('张三',23);
var s2 = new Star('李四',13);
console.log(s1.sing === s2.sing) //true
s1.sing(); //s1实例调用构造函数原型的方法
s2.sing(); //s2实例调用构造函数原型的方法
// 一般情况下,公共的属性定义到构造函数里面,公共的方法我们放到原型对象上
// 构造函数中定义的方法会浪费内存空间 使用原型解决 所有的对象共有同一个函数
// 原型解决的问题就是节省内存空间
/*
每一个构造函数都有一个属性prototype 构造函数.prototype 指向构造函数的原型
构造函数.prototype 就是一个对象,这个对象的属性和方法,都会被构造函数所拥有
所以构造函数的实例对象 可以访问构造函数的原型对象中的成员
*/
</script>
</body>
</html>
6.对象原型
1.对象都会有一个属性 __proto__指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在
2.__protp__对象原型和原型对象prototype 是等价的
3.__proto__对象原型的意义在于为对象的查找机制提供了一个方向,但是它是一个非标准属性,因此在实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Star(name,age){
this.name = name;
this.age = age;
}
Star.prototype.sing = function(){
console.log('唱歌');
}
var s1 = new Star('张三',12);
var s2 = new Star('李四',15);
s1.sing() //实例对象可以访问原型对象的成员
// 对象身上系统自己添加一个__proto__指向我们构造函数的原型对象 prototype
console.log(s1);
console.log(s1.__proto__ === Star.prototype); //true
// 实例对象调用方法 查找规则
// 首先先看 s1对象上是否有sing方法 如果有就执行对象上的sing
// 如果没有就去它的构造函数的原型上查找
</script>
</body>
</html>