JS高级
箭头函数
ES6中新增定义函数方式
( )=>
const fn = ( )=>{ }
箭头函数以小括号开头,小括号里面放置形参的地方 小括号后面要写一个箭头 这是固定语法 小箭头后面 要写一个大括号 大括号 依然表示函数体 这就是定义箭头函数的基本方式
箭头函数没有名字 要如何调用呢?
通常我们都会讲箭头函数赋值给一个变量 变量名字就是函数名字 ,通过变量名字来调用函数就可以了
函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号 、不能写return
<SCRipt>
function sum(num1,num2){
return num1 + num2
}
</SCRipt> //此为传统函数定义
<SCRipt>
箭头函数定义则为:
const sum = (num1, num2) => num1 + num2;
const result = sum(10,20);
condole.log(result);
</SCRipt>
使用传统的函数定义方式为上面
箭头函数为 下面 num1 num2 为函数的形参
在箭头函数中 如果形参只有一个 形藏外侧的小括号也是可省略的
<script>
const fn = v => {
alert(v);
}
fn(20);
</script>
箭头函数有几个使用注意点。
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,箭头函数继承而来的this指向永远不变。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作Generator函数。
箭头函数都是匿名函数,ES5匿名函数的语法糖,并且没有自己的this,arguments,super或new.target。
它的优点是:
(1)简洁的语法。
(2)隐式返回,如 下面的代码可以去掉return,代码一到一行,减少代码量numbers.map((number)=>number*2)
(3)解决了this的指向问题,原生的写法this指向的是调用者,箭头函数this绑定的是定义时的那个对象。如果有对象嵌套的情况下,则this绑定到最近的一层对象上
它的缺点是:
(1)做为构造函数的时候不能使用箭头函数
(2)真正需要this的时候如给元素绑定click事件的时候,执行的回调函数不能使用箭头函数。
(3)我们需要使用arguments对象的时候不能使箭头函数。箭头函数中没有arguments对象。
(4)对象的方法也不可以使用箭头函数
常用数组方法
forEach( ) 方法
forEach () 数组每一个元素都会执行一次回调函数 =类似以前的for forEach 高阶函数 (可以接受一个形参-函数)
for循环可以通过break来打断 forEacah不能通过break 打断
<script>
const arr=['a','b','c'];
//分别打印他们
// arr.forEach(function(value,index){
// console.log(`值是${value} 下标是${index}`);
// });
// arr.forEach((value,index)=>console.log(`值是${value} 下标是${index}`))
arr.forEach(value=>console.log(`值是${value}`))
</script>
注意:forEach() 对于空数组是不会执行回调函数的。
利与弊:foreach虽然是for循环的简化版本,但是并不是说foreach就比for更好用,foreach适用于循环次数未知,
或者计算循环次数比较麻烦情况下使用效率更高,但是更为复杂的一些循环还是需要用到for循环效率更高。
foreach不能对数组或集合进行修改(添加删除操作),如果想要修改就要用for循环。
map( )方法
<script>
map();
function map(){
//map 根据原来的数组 来返回新的数组
//也会循环数组 在循环的回调函数中 可以返回新的数据 组成新的数组
const arr = ['a','b','c'];
//要求返回['我的字母是a','我的字母是b','我的字母是c']
const newArr =arr.map(value=>`我的字母是${value}`); //1,1,1 return了什么 就会被装到数组的每一个元素当中
console.log(newArr);
const list =[9,99,999]; //要求返回10 100 1000
const newList =list.map(value=>value+1)
console.log(newList);
const objArr = [{name:'悟空'},{name:'八戒'},];
const newObjArr = objArr.map(value=>{
value.color='red';
return value
})
console.log(newObjArr);
//数组拼接成字符串数组 转成字符串 插到网页上
const text =['刘德华','张学友','胡歌']
const newText =text.map(value=>`<div>${value}</div>`)
console.log(newText);
//把它转成字符串
const html = newText.join('');
console.log(html);
document.body.innerHTML=html;
}
</script>
04-箭头函数返回对象
<script>
const arr = ['a','b','c'];
//返回 [{name:'a',name:'b',name:'c'}]
const newArr = arr.map(value=>
{return{name:value}});
console.log(newArr);
//次为正确
//{} 这个大括号 就是对象(只是我们的认为 浏览器认为这是块级空间)
//如果 一定要在箭头函数中想要通过省略 return的方式 来返回对象,请一定加上小括号
const func7 = (num)=>({a:123}); //右边加了小括号 表示想要返回 小括号里面的数据return {a:123};
const func8 = (num)=>{a:123}; //undefined
console.log(func7()); //{a:123};
console.log(func8());//undefined
</script>
every ( )
<script>
every();
function every(){
const arr = [1,2,3,4];
//判断数组中的每一个元素,是不是都小于5 如果是 返回true
//every 当中的函数,要求每一个都return 了true 最后every 的返回值才是true
const result = arr.every((value)=>{
if(value<5){
return true;
}else{
return false;
}
});
console.log(result);
}
// every:
// 会返回true 或者false
// 要求数组中每一个元素都符合条件,every 得到true
// 如果空的数组调用了every 得到结果 也是 true
</script>
06-商品单选全选案例
<html>
<head lang="en">
<meta charset="UTF-8" />
<title>08-全选和不全选-every</title>
<style>
* {
margin: 0;
padding: 0;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px solid #c0c0c0;
width: 500px;
margin: 100px auto;
text-align: center;
}
th {
background-color: #09c;
font: bold 16px '微软雅黑';
color: #fff;
height: 24px;
}
td {
border: 1px solid #d0d0d0;
color: #404060;
padding: 10px;
}
.allCheck {
width: 80px;
}
</style>
</head>
<body>
<table>
<tr>
<th class="allCheck">
<input type="checkbox" name="" id="checkAll" />
<span class="all">全选</span>
</th>
<th>商品</th>
<th>商家</th>
<th>价格</th>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米手机</td>
<td>小米</td>
<td>¥1999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米净水器</td>
<td>小米</td>
<td>¥4999</td>
</tr>
<tr>
<td>
<input type="checkbox" name="check" class="ck" />
</td>
<td>小米电视</td>
<td>小米</td>
<td>¥5999</td>
</tr>
</table>
</body>
<script>
let checkAll = document.querySelector('#checkAll');
let checkboxList = document.querySelectorAll('.ck'); // checkboxList 现在是一个伪数组
checkboxList =[...checkboxList]; //伪数组 转为真数组
// 商品全选点击 功能
checkAll.addEventListener('click', function () {
for (let index = 0; index < checkboxList.length; index++) {
checkboxList[index].checked = checkAll.checked;
}
});
// // 给每一个商品绑定点击事件
for (let index = 0; index < checkboxList.length; index++) {
checkboxList[index].addEventListener('click', function () {
// 判断是否达到了全选 条件
// 判断每一个小小的复选框的选中状态 如果都是true,那么就全选
let checked = checkboxList.every((value)=>{
if(value.checked===true){
return true;
}else{
return false;
}
});
checkAll.checked = checked;
});
}
// 两个知识
// 1.伪数组转真正的数组 let newArr=[...伪数组];
// 2.every 要求数组的每一个元素符号要求 every才返回true
// 使用场景,商品全选=》 每一个小商品都选中 全选才勾选
</script>
07-伪数组转真数组
<body>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
const lis = document.querySelectorAll('li')
// console.log(lis.every); 07-伪数组转真数组.html:19 undefined 伪数组
// const liList = [].concat(lis); //concat 合并数组 把空数组和伪数组合并=》返回新数组
// console.log(liList.every);
//最简单的伪数组转真数组办法
// const liList = [...伪数组]
const liList = [...lis];
</script>
</body>
some( )方法
<script>
some();
function some(){
// 检测数组,其中只要有一个元素符合条件,some返回true (every要求每一个都符合)
const arr = [1,2,3,4,5,6,7,8];
//这个数组有没有大于8的
const result = arr.some((value)=>value>8);
console.log(result);
}
/*
every 和some 一起学习
every要求全部都符合
some 最少有一个符合即可*/
</script>
filter( ) 方法
<script>
filter();
function filter(){
//过滤 ,过滤出满足条件的数据 =》新的数组
const arr = [1,2,3,4,5,6,7]
const newArr = arr.filter((value)=>{
//如果return了true 表示当前的value你想要
if(value%2!==0){ //value 1 2 3 4 5 6 7
return true; //value%2!==0 [1,3,5,7]
}else{
return false;
}
})
console.log(newArr);
}
</script>
构造函数
构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋值初始化,它总与new一起使用我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
在js中,使用构造函数时 要注意以下两点:
1.构造函数用于创建某一类对象,其首字母要大写
2.构造函数要和new一起使用才有意义
在ES6之前,对象不是基于类创建的。而是用一种称为构造函数的特殊函数定义对象和他们的特征
创建对象可以通过以下三种 方式
-
对象字面量
-
new Object( )
-
自定义构造函数
<script> //1.利用new Object() 创建对象 const obj1 = new Object(); //2.利用 对象字面量创建对象 const obj2 = {}; //3.利用构造函数创建对象 function Star(name,age){ this.name = name; //属性 this.age = age; //属性 this.sing =function(){ //方法 console.log('我会唱歌'); } } const hu = new Star('胡歌',38); console.log(hu); const ou = new Star('欧豪',28); console.log(ou); ou.sing(); //sing 为方法 </script>
new在执行时会做的四件事
- 在内存中创建一个新的空对象
- 让this指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要retum)
JavaScript的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数的内部添加。通过这两个方式添加成员,就分别称为静态成员和实例成员。
<script>
//构造函数中的属性和方法我们称为成员,成员可以添加
function Star(name,age){
this.name = name; //name属性
this.age = age; //age属性
this.sing =function(){
console.log('我会唱歌'); //sing方法
}
}
const hu = new Star('胡歌',38);
//1.实例成员 就是构造函数内部通过this添加的成员 name age sing 就是实例成员
//实施成员只能通过实例化对象来访问
console.log(hu.name);
hu.sing();
// 错误 console.log(Str.name); //不可以通过构造函数来访问实例成员
// 2.静态成员 在构造函数本身上添加的成员 sex就是静态成员
Star.sex = '男';
//静态成员只能通过构造函数来访问
console.log(Star.sex);
// 错误 console.log(hu.sex); //不能通过对象来访问
</script>
- 静态成员:在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问
- 实例成员:在构造函数内部创建的对象成员成为你实例成员,只能由实例化的对象来访问
构造函数的问题
构造函数方法很好用 但是存在浪费内存问题。
上面的name 和age 是简单数据类型 还好说 但是里面的sing方法是个函数 而函数又是个复杂数据类型
当创建胡歌个对象的时候 会再单独再开一个内存空间来存放这个复杂数据类型 也就是把这个函数放进去
所以我们希望所有的对象使用同一个函数,这样就比较节省空间
构造函数原型
构造函数通过原型的分配的函数是所有对象共享的。
JavaScrip规定,每一个构造函数都有一个prototype属性,指向另一个对.注意这个prototype就是一个对象,这个对象的所有有属性和方法,都会被构造函数有拥有。
我们可以把那些不变的方法,直接用prototype对象上,这样所有对象的实例就可以共享这些方法。
构造函数的 原型对象 追加的方法
<script>
//构造函数中的问题
function Star(name,age){
this.name = name; //name属性
this.age = age; //age属性
}
Star.prototype.sing = function(){
console.log('我会唱歌');
}
const hu = new Star('胡歌',38);
const nie = new Star('聂成林',23)
console.log(hu.name);
hu.sing();
console.log(nie.name);
nie.sing();
</script>
???
1.原型是什么?
一个对象,我们也称为prototype为原型对象
2.原型的作用是什么 ?
共享方法
注意:一般情况下,我们的公共属性定义到构造函数里面,公共的方法我们放到原型对象身上
对象原型 proto
对象都会有一个属性 proto 指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是要问对象有 proto 原型的存在。
- _proto_对象原型和原型对象prototype是等价的
- proto 对象圆的意义就在于 为对象的查找机制提供一个方向,或者说一条线路,但是它是一个非标准,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype
小结:原型对象 ---构造函数 一般情况
构造函数内只放属性 name age color height
对应原型上 都是放 方法==》就是函数 复杂类型
![image (md.zbztb.cn/uploads/494… (1).png)
面向对象的初体验1
<script>
function MyImg(src){
const img = document.createElement('img');
img.src = src;
img.style.width='250px'
document.body.appendChild(img);
}
const img1 = new MyImg('./imgs/1.webp')
const img2 = new MyImg('./imgs/2.jpg')
</script>
面向对象的初体验2
<script>
function MyImg(src){
const img = document.createElement('img');
img.src = src;
img.style.width='250px'
document.body.appendChild(img);
this.dom = img; //把图片dom元素 添加到 this 对象的一个属性 dom属性
}
//原型
MyImg.prototype.scale =function(){
//图片放大缩小的本质就是给图片的dom元素 添加一个class(类)
// console.log(this.dom);
this.dom.classList.add('scale')
}
const img1 = new MyImg('./imgs/1.webp')
const but = document.querySelector('button')
but.addEventListener('click',function(){
img1.scale(); //img1 调用了scale这个方法
})
</script>
面向对象的初体验3
<body>
<button>变</button>
<script>
function Div(text){
const div =document.createElement('div');
div.innerText=text;
document.body.appendChild(div);
this.dom = div;
}
Div.prototype.changeColor = function(color,size){
// this.dom 等于上述div
this.dom.style.backgroundColor = color;
this.dom.style.fontSize =size;
}
const divObj1 = new Div('这是个普通的div1')
const divObj2 = new Div('这是个普通的div2')
const divObj3 = new Div('这是个普通的div3')
const but =document.querySelector('button');
but.addEventListener('click',function(){
divObj1.changeColor('red','20px')
divObj2.changeColor('aqua','35px')
divObj3.changeColor('yellow','50px')
})
</script>
</body>
面向对象的初体验4
<script>
// 需求:点击哪张图片,哪张图片变成边款圆角为50%
//构造函数
function MyImg(src) {
const img = document.createElement("img");
img.src = src;
img.style.width = "370px";
img.style.transition = "2.3s";
document.body.appendChild(img);
this.dom = img;
//给图片绑定点击事件
img.addEventListener("click", function () {
img.style.borderRadius = "50%";
});
}
const img1 = new MyImg(
"./imgs/83cc8615214a62c1c3f3a67b9c5fee32--2780999425.jpg"
);
const img2 = new MyImg("./imgs/2.jpg");
const img3 = new MyImg("./imgs/新建文件夹IMG_0131.JPG");
</script>
深夜听着歌 写着笔记 突然就想家了
望我们不忘初心
砥砺前行