认识高级js
函数箭头
匿名函数可以 用函数箭头表示,函数箭头写法简单,比较优雅
let text = function (){
}
这是普通匿名函数写法
let text = ()=>{
}
这是箭头函数写法 省略了 function
1.如果函数体只有一句,那么可以省略{},同时默认会返回函数体的结果,不能写return
2.如果只有一个参数,那么可以省略()
3.如果没有参数,()也不能省略
let test = (a,b) => a + b // 不能有大括
const ter = (num)=> num +100
console.log(ter)
将上一句代码和下面的代码进行相加
let res = test(100)
console.log(res);
结果是200
forEach遍历
const arr = ['a','b','c']
forEach 正常写法
arr.forEach(function (){
console.log(`值是 ${value} 索引是${index}`)
)
箭头函数简写写法
arr.forEach((value,index)=>console.log(``值是${value} 索引是${index} ``))
map数组常用方法
map 方法 表示 把一个旧的数组 ,重新组装成一个新得数组
map()
function map(){
const arr = ['我自己','你自己','她']
const arr1 = [1,2,3,4,5]
const newArr = arr.map(value =>{
console.log(`爱` value)
输出结果为 [爱我自己,爱你自己,爱她]
const str = arr.map(value => value +1)
输出结果为 [2,3,4,5,6]
})
}
map()
function map(){
const arr = ['a','b','c']
const arrtex = arr.map(value => ({name:value}))
// 箭头返回值 ,表示 返回 三个 对象 数组 因为加了{}
console.log(arrtex);
}
every数组常用方法
every 是一个数组方法 ,伪数组不能使用,转换成真正的数组就能用
这个方法 是比较 只有 数组 里面全部 比较为 true ,才 返回true
every 只能返回 true 或者 false
要求数组里面每一个元素都符合条件,为true,才会返回true,类似于&&与运算
注意!!!如果空的数组调用了eveny,得到的结果也是为true
function every(){
const arr = [1,3,5,7]
const arrTs = arr.every((value) =>{
// arr.every表示选中 arr数组 ,使用every方法 ,value代表的是arr数组里面的值
if(value < 8){
return true
}else{
return false
}
})
console.log(arrTs);
}
every()
比较数组里面的值 全部为true 才返回ture
伪数组转数组方法
伪数组转 数组 用 这样一个 方法 很简单
接收元素 = [...伪数组]
filter数组常用方法
filter()
function filter(){
// fliter 数组方法就是 过滤掉你不想要的 ,然后 需要的 会自动 创建一个
// 新的数组 和 js基础 % 类似
const arr = [1,2,3,4,5,6,7,8,9]
const arrIn = arr.filter(value => value % 2 !== 0)
console.log(arrIn);
}
some数组常用方法
/* some 的意思就是 只要有 一个 条件满足 则返回 true 和逻辑或||相似
而 every 就是 全部 为true 才返回true 或 逻辑与|| 相似 */
function some(){
const arr = [1,2,6,9,3,5]
const arrIn = arr.some(value => value > 8)
console.log(arrIn);
}
字面量函数
// 字面量 创建对象不方便维护 因为要修改属性还得一个一个修改
// 假如现在我想要修改name属性 修改成userName 处理起来就比较麻烦
let obj1 = {
name:'我自己',
height: 167,
}
let obj2 = {
name:'我自己',
height: 167,
}
let obj3 = {
name:'我自己',
height: 167,
}
工厂函数
// 工厂函数,createperson
// 工厂函数 有点是 方便复用 ,缺点是无法继承 一样的属性名 一样的样式 爸爸和儿子
// 儿子 继承 不到 爸爸的 样式
function createPerson(name,age,height){
return {
names:name,
ages : age,
heights : height
}
}
const obj1 = createPerson('孙悟空',18,150)
console.log(obj1);
const obj2 = createPerson('沙和尚',18,150)
console.log(obj2);
const obj3 = createPerson('猪八戒',18,150)
console.log(obj3);
构造函数
function createPerson(name,height){
this.name = name,
// 构造函数 必须是 this.xxx =
this.height = height
}
const obj1 =new createPerson('我自己',22)
// 传实参到形参必须 要以 new 开头,加上函数名字
console.log(obj1);
console.log(obj1.name);
构造函数性能问题
// 构造函数 优点 复用方便 拥有继承性 还有很多优势
// 专业术语
// createPerson() 叫做构造函数
// new createPerson () 叫做 实列
function createPerson(name,age,height){
this.name = name;
this.age = age;
this.height = height;
}
const obj1 = new createPerson('她',18,155)
// 必须要通过 一个 new方式 来创建 对象
console.log(obj1);
console.log(obj1.name);
构造解决性能问题
function CreatePerson(name,say) {
this.name = name
this.say = say
}
const obj1 = new CreatePerson('孙悟空')
const obj2 = new CreatePerson('猪八戒')
// console.log(obj1.say===obj2.say);
// console.log();
// 1 obj1.say ==obj2.say,两个比较是为false,因为
// 我们每创建一个对象,都会开辟一个新的内存地址,两个比较是为false内存地址
// 都不一样 所以返回结果为false,内存消耗比较大,性能自然而然就不那么好了
console.log(obj1.say === obj2.say);
// 2 解决构造函数性能问题 ,想要解决性能问题 ,我们只需要把say方向变成全局变量
// 让每一次创建新的对象的时候,this指向都会指向我们构造函数外面的say方法,
// 因此,全局变量的say方法,我们无论创建多少个对象,就会一起存放到全局变量say
// 方法里面
构造函数 污染全局变量
// 如果函数方法 作为全局变量 也会污染全局变量,
// 因为一个大型项目当中,你不可能记得你用了哪个
// 方法,然后如果你下面设置的方法刚好和上面的方法
// 函数一样,机会覆盖掉,就会出错
function say(){
console.log('你吃饭了吗');
}
function CreatePerson(name){
this.name = name
this.say = say
}
const obj1 = new CreatePerson('孙悟空')
const obj2 = new CreatePerson('猪八戒')
console.log(obj1.say === obj2.say);// 如果为true 表示优化过的
console.log(obj1.say === obj2.say);// 如果为false 表示没有优化过的
// 函数作为全局变量 方法 提取出去
/* 优点 : 方便复用 代码维护 也解决了 性能 obj1.say ===obj2.say 只要
两者相等,就可以说是解决了性能问题了,因为两个对象都存储到一个
内存地址上了 */
原型对象 最终选择
// 原型对象可以很好的帮我们解决了 姓名 全局变量污染 的问题
// 原型对象prototype 才是最终要选择用的一个方法
// 原型对象 是任何构造函数对存在的一个对象 prototype
// 作用: 构造函数看是人, 原型对象 就是人的DNA
// 如果我们修改了DNA,那么通过构造函数创建实例都会一起发生修改
// 如果我们在DNA上新增了一些东西,对应实例一样会被新增
function CreatePerson(name){
this.name = name
}
CreatePerson.prototype.i= ()=>{
console.log('你吃饭了吗?');
}
const obj1 = new CreatePerson('悟空')
const obj2 = new CreatePerson('八戒')
console.log(obj1.i()===obj2.i()); // 等于true 没有性能问题
// 有污染全局变量的问题吗 没有
// 小结 原型对象-构造函数 一般情况
// 构造函数内只放属性 name 、age、color、height
// 对应原型上 都是放 方法 = 函数
原型继承
// 这个就是 ii函数 借调 cc函数里面的 属性
// 假如是 我们想借调 cc 里面的属性 ,原理就是 谁借用他,那个方法就属于谁的
// 我们ii 借调cc 函数属性 ,只需要在 ii 函数里面 写上 借调函数名.call
// (this,表示当前函数借调,再添加上 想要借调的属性名 name age height)
function cc(name,age,height){
this.uname = name
this.age = age
this.height = height
}
function ii(name,age,height,color){
cc.call(this,name,age,height)
// 这一行代码解决了 继承问题
this.color = 'red'
// 借调函数里面没有color 这个属性,所欲说我们要自己创建
}
const obj = new cc('我自己',22,167)
const obj1 = new ii('梁祺星','22岁',167,'red')
console.log(obj1);
梁祺星 22岁 167 red
console.log(obj);
输出结果为 我自己 22 167
属性方法继承
function Person(name, age) {
this.username = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(this.username, this.age)
; // 我是谁 我的年龄是
};
// const p1 = new Person('我',19)
// console.log(p1.say());
// 如果是输入 say方法的话 只会输出 父元素的值
// Person.prototype.say = function () {
// console.log(this.username1, this.age)
// ; // 我是谁 我的年龄是
// };
Person.prototype.show = function () {
console.log(this.username + ' 秀肌肉');
};
function Student(name, age, color) {
Person.call(this, name, age)
this.color = 'red'
}
const s1 = new Student('梁', 22, 'green')
Student.prototype.say = Person.prototype.say
Student.prototype.show = Person.prototype.show
s1.say()
输出结果为 梁 22
s1.show()
输出结果为 梁 秀肌肉
函数参数默认值
function cc(mag = '你好', i = '我号') {
console.log(mag, i);
}
cc('大家好')
输出结果为 大家好
要是我们没有进行 调用函数 没有 传实参,那么他就会 输出一个你好,
要是我们 传了实参,那么 输出的就是我们的实参 相当于进行了判断
cc('我很好', '她也很好')
要是我们 只传了一个 实参 ,有两个 属性 ,另外一个就会显示默认属性 i
如果有两个 属性 ,没有 传参 就会输出 自定义属性的值
对象简写
/* 对象属性方法 简写
如果变量名和 对象属性一致 ,则可以 直接在 对象大括号里面输入变量名
就可以 得到 变量名得值 */
const name = '你好'
const age = '22岁'
const obj = {
name,
age
}
console.log(obj);
输出结果为 name :你好 age : 22岁
const obj1 = {
say = function(){
}
可以进行简写
say() {
} 这样就可以简写了
}
解构
<div data-index = '100'></div>
<script>
const {index} = document.querySelector('div').dataset
console.log(index);
// 简写属性
const arr =[ '猪八戒','白龙马','孙悟空','小乔']
// 希望 声明四个变量 a = 悟空 b = 八戒
// 数组解构
const [a,b,c,d] = arr
console.log(a,b,c,d);
// 相当于是
// const [a, b, c, d] = ['悟空', '八戒', '龙马', '三藏',"沙僧"];
const obj ={
name:'悟空',
age: 18,
height:167
}
// 对象解构
// 声明三个变量来接收obj得三个属性
const {name,age,height} = obj
console.log(name,age,height);
// 简写属性
</script>
拓展运算符
// ...表示获取剩下 的 数组
// const arr = [1,2,3,4,5,6]
// const [a,b,...c] = arr
// console.log(a,b,c);// a 和b 对应数组的里面的内容,c就是取剩下组成一个新的数组
// 输出 1 2 [3,4,5,6]
// 获取剩下的 对象
// const {a,...c} = {a:1,b:2,c:3}
// console.log(a,c);// a 对应数组的里面的内容,c就是取剩下组成一个新的对象
// 输出 a:1 {b:2,c:3}
/* const [...a] =[1,2,3,4]
console.log(a) //输出结果是 1 2 3 4
console.log(a.map);
// ...args延展符 有数组 功能 */
// 计算一个和
function call(...args){
let sum = 0
args.forEach(value => sum += value);
console.log(sum);
}
call(1,2,3,4,5)
// 剩余运算符
/* 1 数组中 const [a,b,...c] = [1,2,3,4,5,6,7] a是1 b是2 c是一个数组 [34567]
应用场景 把伪数组转成真正的数组
2 对象中 const {a,...c} = {a:1 b:2 c:3} a是1 c是 {b:2 c:3}
3 函数的形参中 function calc(...args) 等于 {args[1,2,3]}
calc(1,2,3) */
拓展 展开 延展
const obj ={
username : '悟空',
age : 18
}
// 展开 ...用法
// 新创建一个对象,这个对象拥有obj所以的属性
// ...延展 表示 把 obj里面的 属性延展开 然后拿到obj里面的属性
// 可以添加属性color
const obj1 = {...obj,color:'yellow' }
// 同时并且加多color:"red"属性
console.log(obj1);
// 输出结果为 username: '悟空', age: 18, color: 'yellow'}
展开运算符
// 展开运算符
/* const obj1 = {
name:'梁',
age : 18,
hieght :167
}
const obj2 = obj1
obj2.color = 'red'
console.log(obj1);新的对象
console.log(obj2);旧的对象
对象是引用类型 */
/* 写 = 将 obj2的地址 给了一份 Obj1 两个变量指向的地址同样的 同一个对象
这样直接赋值方法是错误的,我们修改了值 ,两个对象的值都会改变
因为内存地址是同一个 */
set对象数组
/* Set.add 可以去重,如果你添加的内容已经是有的,那么 再用Set.add添加
将不会有结果,Set.add就是去重,es6 自带的去重效果 */
let arr = ['b','a','c',1,2]
const newArr = new Set(arr)
// new Set 方法可以将一个数组转换成 一个对象
newArr.add(3)
// 给对象添加 值 3
newArr.add(4)
const isn = [...newArr]
// 把newArr转换成数组 赋值给 isn
console.log(isn);
// 输出结果是 数组 b a c 1 2 3 4
band call apply 继承传参
// 继承方法 并传参数
const obj = {
name: '大朗',
say(a, b) {
console.log(this.name + ' ' + a + ' ' + b);
}
}
const person = {
name: '西门大官人'
}
obj.say.call(person, 1, 2)
// call传参数 直接 对象名 加 参数 1 参数2
obj.say.apply(person, [1, 3])
// apply 直接 对象名 加 数组,把参数放进数组里面
const i = obj.say.bind(person)
// bind 直接 对象名 ,然后会返回一个函数返回值的,需要我们
// 自己调用 参数 直接放在 调用函数的括号 i(参数1,参数2)
i(1, 4)
this指向
// 谁借调 方法 this 就指向谁
const obj = {
name: '老王',
say() {
console.log(this.name + ' 翻墙');
}
}
const person = {
name: '大朗'
}
obj.say.call(person)
// all 方式来修改this的指向
// obj.skill.call(person);// 大郎 借用老王的方法
obj.say.apply(person)
// apply 方式来修改this的指向
// obj.skill.apply(person); // 大郎 借用老王的方法
const fun = obj.say.bind(person)
fun()
/* bind 方式修改this指向 不过他不会给你输出 数据
而是给你一个函数返回值 ,你还要 创造一个变量来接收
这个函数返回值 然后 调用 */
es6面向对象 语法结构
// es6 面向对象写法 看到class就知道是 面向对象了
class person {
// constructor是固定写法 ,把属性都写在constrctor里面
constructor(name) {
this.name = name
}
// 把方法都写在say里面就好了
say() {
console.log(this.name + ' say方法被调用啦');
}
}
const obj = new person('悟空')
const obj1 = new person('八戒')
obj.say()
// 输出结果为 悟空 say方法被调用啦
obj1.say()
// 输出结果为 八戒 say方法被调用啦
es6 继承 父元素 属性 方法
class person {
constructor(name) {
this.name = name
}
say() {
console.log('翻墙 ' + this.name);
}
}
class person1 extends person {
// class是固定写法 person1是 函数名 extends 是继承 person 符元素
// 相当于 person1 继承 父元素 的属性 和属性值
constructor(name) {
// 写了 constructor 必须要写 super
super(name)
// 在es6直接 super(要继承的属性) 就可以了
// super在es5 表示 person.call(this.name)
}
}
const obj1 = new person1('梁祺星')
/* 父元素没有数值型,所以我们手动
添加一个属性值上去 */
console.log(obj1);
obj1.say()
// 输出结果 是 梁祺星 翻墙
es6 三种定义方法
class person {
constructor() {
// this.name = name,
// this.age = age,
// this.height = height
}
// say(){}定义方法 最性能最好的 而且不会全局污染
say() {
console.log('say');
}
// 不推荐
say1 = function () {
console.log('say1');
}
// 不推荐
say2 = () => {
console.log('say2');
}
}
const a1 = new person()
const a2 = new person()
console.log(a1.say === a2.say); true
console.log(a1.say1 === a2.say1); false
console.log(a1.say2 === a2.say2); false
\