JS进阶
闭包
闭包:会有内存泄漏的问题
函数动态参数
不确定形参时用(箭头函数中没有arguments)
函数剩余参数
展开运算符
箭头函数中的this
解构赋值
数组结构
对象结构
多级对象解构
forEach
与map不一样的是,只遍历不会返回数组
map会返回一个数组
类似于高级版的for循环
const numbers = [1, 2, 3];
numbers.forEach(num => {
console.log(num * 2); // 输出: 2, 4, 6
});
// numbers 仍然是 [1, 2, 3]
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // 输出: [2, 4, 6]
// numbers 仍然是 [1, 2, 3]
filtter
创建对象
内置的构造函数
Object ,Array , String,Number
Object
1.object.key( ) , object.value( )
2.object.assign( )
Array
数组常见其他方法
伪数组转化为真数组
首先我们要知道伪数组是什么:伪数组(也称为类数组对象)是一种具有 length 属性但不具备数组方法(如 push、pop、forEach 等)的对象,以下是一些例子:
1. arguments 对象
在函数内部,arguments 是一个伪数组,包含传递给函数的所有参数。
function example() {
console.log(arguments); // 伪数组
console.log(Array.isArray(arguments)); // false
}
example(1, 2, 3);
2. document.querySelectorAll
document.querySelectorAll 返回的是一个 NodeList,它是一个伪数组。
const elements = document.querySelectorAll('div'); // 伪数组
console.log(elements); // NodeList
console.log(Array.isArray(elements)); // false
转化方法一:Array.from
字符串中常见方法
1.split()
const str='pink,sjid'
console.log(str.split(','));//['pink', 'sjid']
const str1='2022-4-12'
console.log(str1.split('-'))// ['2022','4','12']
2.split()
const str = "Mozilla";
console.log(str.substring(1, 3));
//"oz" 不包含结束索引号
console.log(str.substring(2));
// "zilla"
3.startsWith()
const str = "To be, or not to be, that is the question.";
console.log(str.startsWith("To be")); // true
console.log(str.startsWith("not to be")); // false
console.log(str.startsWith("not to be", 10)); // true
4.includes()
const str = "To be, or not to be, that is the question.";
console.log(str.includes("To be")); // true
console.log(str.includes("question")); // true
console.log(str.includes("nonexistent")); // false
console.log(str.includes("To be", 1)); // false
console.log(str.includes("TO BE")); // false
console.log(str.includes("")); // true
练习案例
<!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></div>
<script>
const gift = '50g的茶叶,清洗球'
// 1. 把字符串拆分为数组
// console.log(gift.split(',')) [,]
// 2. 根据数组元素的个数,生成 对应 span标签
// const str = gift.split(',').map(function (item) {
// return `<span>【赠品】 ${item}</span> <br>`
// }).join('')
// // console.log(str)
// document.querySelector('div').innerHTML = str
document.querySelector('div').innerHTML = gift.split(',').map(item => `<span>【赠品】 ${item}</span> <br>`).join('')
</script>
</body>
</html>
Number
1.toFixed()
const numObj = 12345.6789;
numObj.toFixed(); // '12346';四舍五入,没有小数部分
numObj.toFixed(1); // '12345.7';向上舍入
numObj.toFixed(6); // '12345.678900';用零补足位数
(1.23e20).toFixed(2); // '123000000000000000000.00'
(1.23e-10).toFixed(2); // '0.00'
(2.34).toFixed(1); // '2.3'
(2.35).toFixed(1); // '2.4';向上舍入
(2.55).toFixed(1); // '2.5'
// 它向下舍入,因为它无法用浮点数精确表示,并且最接近的可表示浮点数较小
(2.449999999999999999).toFixed(1); // '2.5'
// 向上舍入,因为它与 2.45 的差值小于 Number.EPSILON。
// 这个字面量实际上编码和 2.45 相同的数值
(6.02 * 10 ** 23).toFixed(50); // 6.019999999999999e+23;大数仍然使用指数表示法
-2.34.toFixed(1); // -2.3,数字
(-2.34).toFixed(1); // '-2.3'
编程思想
面向过程编程
面向对象编程
封装性,继承,多态 很适合大项目
构造函数
JS中 构造函数体现了面向对象的封装特性
原型
原型可以解决构造函数中浪费内存的问题
构造函数和原型里面的this指向
案例--求和,最大值
constructor 构造函数
function Star(name){
this.name=name
}
let ldh=new Star('刘德华')
console.log(Star.prototype)//输出constructor
对象原型
问题: 为什么创建的实例对象可以使用在原型对象(prototype)中追加的方法呢?
这就要考虑到实例对象中的对象原型了!
function Star(name){
this.name=name
}
let ldh=new Star('刘德华')
console.log(ldh.__proto__ === Star.prototype)
//输出true
console.log(ldh.__proto__.constructor === Star)
//输出true
原型继承
把公共属性放入原型上
const Person={
eays:2,
head:1
}
function Woman(){
}
Woman.prototype = Person
Woman.prototype.constructor = Woman
const lh = new Woman()
console.log(lh.eays);
console.log( Woman.prototype.constructor);
但是存在一些问题:给Woman添加特殊的方法时会同时添加到Man中
原型链
处理this
改变this指向
call()
apply()
call和apply 的共同点:都是调用函数,都能改变this指向 区别:参数不一样,apply必须传递数组,call传递普通参数 如果apply()不想改变指向,那么设置为apply(null,[])也是合理的
bind()
<button>发送短信</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log('被点击了');
this.disabled = true
setInterval(function () {
this.disabled = false
//此时的this指向的是window所以一秒钟之后按钮还是被禁用
console.log(this);
}, 3000)
})
</script>
运行结果:
更改:用bind()
<button>发送短信</button>
<script>
const btn = document.querySelector('button')
btn.addEventListener('click', function () {
console.log('被点击了');
this.disabled = true
setInterval(function () {
this.disabled = false //此时的this指向的是window所以一秒钟之后按钮还是被禁用
// 也可以写成: btn.disabled = false
console.log(this);
}.bind(btn), 3000)//bind(btn)使得this指向了btn
//还可以写出.bind(this): bind()函数在定时器function()的外部,所以bind(this)这里的this也是指向btn ;
// setInterval(() => {
// this.disabled = false //这里的this 指向的是btn
// //箭头函数没有this的指向,会找上一级函数
// }, 3000)
})
</script>