JavaScript高级-自我总结

JavaScript 知识点

1. 作用域

  • 全局作用域
    • 【函数外】,在全局作用域定义的变量
    • 全局变量可以在任何地方使用
  • 局部作用域
    • 【函数内】,在局部作用域定义变量
    • 局部变量只能在当前作用域使用
  • 块级作用域(ES6)
    • 【大括号内】,在块级作用域定义的变量
    • 块级变量只能在当前块级使用

2. 声明变量关键字

  • varletconst(常量)

  • varlet 区别:

    1. var声明的比那辆属于window, let声明的变量不属于window
    2. var声明的变量不具有块级作用域, let声明的变量具有块级作用域
    3. var可以重复声明,let不可以重复声明
  • conts(常量)

    1. const声明的变量不属于window
    2. const声明的变量具有块级作用域
    3. const不可以重复声明
    4. const声明的变量必须初始化有值
    5. const声明的变量不允许改值
    • 建议
      1. 声明常量时,常量名全大写
      2. 不变的值建议用常量定义

3. 作用域链

  • 作用域链:由作用域串联起来链

  • 作用:提供查找变量的机制

  • 当一个作用域访问一个变量时,先从当前作用域查找,如果不存在这个变量,那么就会往上级查找

4. 闭包

  • 闭包
    • 一个作用域有权访问另外一个作用域的局部变量
    • 子函数访问了父函数的局部变量,然后把子函数返回到外面
  • 作用
    • 延伸变量的使用范围,避免变量污染
// fn 为闭包函数
function fn () {
    let num = 666
    return function fun () {
        console.log( num )
    }
}
let re = fn()
re()  // 666

5. 预解析

  • js运行三部曲
    1. 先语法分析 扫面一遍看看有没有语法错误
    2. 预解析
    3. 解释执行 解释一行执行一行
  • 预解析四部曲
    1. 创建AO对象
    2. 找形参和变量声明,将变量和形参名作为AO属性名,值为 undefined
    3. 将实参值和形参值统一
    4. 在函数里面找函数声明,值赋予函数体
  • 预解析:代码执行之前先要预解析
    • 变量:带有声明的变量,也叫变量的提升
      • 把变量的声明语法提升到当前作用域的最前面
      • 注意:只声明不复制
    • 函数:带有名字的函数
      • 把函数的声明语法提升到当前作用域的最前面
      • 注意:只声明不调用
    • 预解析
      • 函数声明整体提升 – 声明变量提升 - 变量不赋值
      • 变量 声明提升 – 声明函数提成 - 函数不执行
  • let 生命前不可以用,生命后才可以使用,constlet
function test(a, b){
    console.log(a); // function a () {}
    console.log(b); // undefined
    var b = 234;
    console.log(b); // 234
    a = 123;
    console.log(a); // 123
    function a () {}
    var a;
    b = 234;
    var b = function () {}
    console.log(a); // 123
    console.log(b); // function () {}
}

6. 函数

6.1 参数默认值

// 求任意两个数的和
function getSum ( a = 0, b = 0 ) {
  // let a = 0
  // let b = 0
  let sum = a + b
  console.log( sum )
}
getSum( 1 ) // 1 + 0 = 1
getSum() // 0 + 0 = 0
getSum( undefined, 6 ) // 0 + 6 = 6

6.2 动态参数 - arguments

  • 遇到参数不固定的情况:arguments
  • arguments: 函数内部的特殊对象,用于接收所有参数
  • 注意:
    • arguments 是一个伪数组
  • 建议:
    • 如果参数不固定用arguments, 但是如果参数固定的情况下直接用形参
function fn2 () {
  // console.log( arguments ) // arguments = [1, 2, 3, 'a', 'aa']
  for ( let i = 0; i < arguments.length; i++ ) {
    console.log( arguments[i] )
  }
}
// 实参的个数不确定
fn2( 1, 2, 3, 'a', 'aa' ) // 1 2 3 a aa

// 求若干个数的最大值
function getMax () {
  let max = arguments[0]
  for ( let i = 1; i < arguments.length; i++ ) {
    if ( max < arguments[i] ) max = arguments[i]
  }
  console.log( max )
}
getMax( 123, 5, 62, 81, 21, 564, 551, 621, 22 )

6.3 ... - 剩余参数、扩展运算符

6.3.1 剩余参数 - ...
  • ES6

  • 接收剩余参数 ...

  • 只能放到形参的最后一位

function fn1(a, b, ...c) {
  console.log(a, b, c) // 刘备 关羽 ['张飞', '黄忠', '马超']
}
fn1("刘备", "关羽", "张飞", "黄忠", "马超")

function fn2(...a) {
  console.log(a) // 刘备 关羽 ['张飞', '黄忠', '马超']
}
fn2("刘备", "关羽", "张飞", "黄忠", "马超") // ['刘备', '关羽', '张飞', '黄忠', '马超']

// 求若干数的和
function getSum(...ary) {
  // console.log( ary ) // [3, 6, 4, 84, 84, 89, 5, 12]
  let sum = 0
  for (let i = 0; i < ary.length; i++) {
    sum += ary[i]
  }
  console.log(sum)
}
// 任意个数的实参
getSum(3, 6, 4, 84, 84, 89, 5, 12) // 287
6.3.2 扩展运算符 - ...
let arr = [23, 25, 69, 84, 92, 62]
// console.log(Math.max(arr)) // 报错 Math.max(这里需要一堆数而不是一个数组)
console.log(...arr) // 23 25 69 84 92 62
let re2 = Math.max(...arr)
console.log(re2) // 92

6.4 箭头函数 - () => {}

  • 箭头函数
    • let fn = () => {}
    • let fn = ( a, b ) => {return a * b}
    • let fn = a => {return a * a}
    • let fn = a => a * a
// 1.箭头函数基本用法
let fn1 = (a, b) => {
  console.log(a, b)
}
fn1(11, 22) // 11 22

// 2.箭头函数其他形式
// 2.1 如果函数的参数只有一个,那么可以省略小括号
let fn2 = (a) => {
  return a * a
}
console.log(fn2(3)) // 9

// 2.2 如果函数只有一行代码,那么可以省略大括号
// 注意:如果省略了大括号,那么会默认返回结果
let fn3 = (a) => a * a
console.log(fn3(6))

// 3. 箭头函数使用场景:
// 3.1 间歇定时器
;setInterval(() => {
  console.log("aaa")
}, 1000);

// 3.2 forEach遍历数组
[1, 2, 3].forEach((item) => console.log(item))
  • 箭头函数注意事项

    1. 在箭头函数中不存在arguments,所以箭头函数不可以使用arguments
    let fn1 = ( ...a ) => {
      // console.log( arguments ) // 报错
      console.log( a ) // [1, 5, 6, 8, 651, 5]
    }
    fn1( 1, 5, 6, 8, 651, 5 )
    
    1. 箭头函数不存在预解析,所以是用箭头函数的时候必须先声明后调用
    let fn2 = () => {
      console.log( 123 )
    }
    fn2()
    
    1. this: 指向问题
    • 箭头函数中,this指向的是上级作用域的this(指向所在作用域的this
    • 建议:有this不建议使用箭头函数
    let obj = {
      uname : '张三丰',
      fei : function () {
        console.log( this ) // Object
    
        setInterval( function () {
          console.log( this ) // window
        },1000 )
    
        setInterval( () => {
          console.log( this ) // Object
        },1000 )
      }
    }
    obj.fei()
    
    1. 箭头函数可以有 事件对象
    document.documentElement.addEventListener('click', e => {
      console.log( e.target ) // html
    })
    
    • 箭头函数 this 指向例子
    document.documentElement.addEventListener('click', function (e) {
      console.log( this ) // html
    })
    document.documentElement.addEventListener('click', e => {
      console.log( this ) // window
    })
    

6.5 函数的注意事项

  1. 函数如果有return, 会把结果返回

  2. 如果函数只写return不写值,那么默认返回一个undefined

  3. 如果函数不写return,在函数执行完成之后也会返回undefined

7. 解构赋值

  • 作用
    • 解开数据结构,赋给变量 == 赋值给变量的一种简介写法

7.1 数组解构 - 核心:一一对应

let [a, b, c, d, e] = ['刘备', '关羽', '张飞', '黄忠', '马超']
console.log( a, b, c, d, e ) // 刘备 关羽 张飞 黄忠 马超
// 1.1 变量少值多
let [a1, b1, c1] = ['刘备', '关羽', '张飞', '黄忠', '马超']
console.log( a1, b1, c1 ) // 刘备 关羽 张飞
// 1.2 变量多值少
let [a2, b2, c2, d2, e2, f2, g2] = ['刘备', '关羽', '张飞', '黄忠', '马超']
console.log( a2, b2, c2, d2, e2, f2, g2 ) // 刘备 关羽 张飞 黄忠 马超 undefined undefined
// 1.3 按需取值
let [, a3, , , b3] = ['刘备', '关羽', '张飞', '黄忠', '马超']
console.log( a3, b3 ) // 关羽 马超
// 1.4 剩余值取法
let [a4, b4, c4, ...d4] = ['刘备', '关羽', '张飞', '黄忠', '马超']
console.log( a4, b4, c4, d4 ) // 刘备 关羽 张飞 ['黄忠', '马超']
// 1.5 多维结构
let [, a5, , [b5, , c5]] = ['刘备', '关羽', '张飞', ['孙悟空', '猪八戒', '沙悟净']]
console.log( a5, b5, c5 ) // 关羽 孙悟空 沙悟净

7.2 对象解构 - 核心:把属性名当作变量名

let uname = '哇哈哈'
// 注意:如果已经存在某个变量名,用冒号改名字
let { uname:userName, score, age, agee }  = {
  uname : '张三丰',
  age : 22,
  sex : '男',
  inedx : 6,
  score : 99
}
// 注意:取的对象属性里没有,输出就是undefined
console.log( userName, score, age, agee ) // 张三丰 99 22 undefined

// 2.1 多维结构
let {car : {width, height}} = {
  windth : '150CM',
  windth : '150CM',
  car : {
    color : 'red',
    width : '550CM',
    height : '850CM',
  }
}
console.log( width, height ) // 550CM 850CM

8. 对象-构造函数

8.1 创建对象

8.1.1 字面量创建对象
// 1. 字面量创建对象
let obj = {
  // 属性 : 属性值
  // 键 : 值
  // 成员
  uname : 'HiHi',
  sex : '男',
  age : 22,
  // 方法
  say : () => console.log('我说了一句话'),
  bai : () => console.log('拜拜')
}
// 1.1 访问属性:
// 语法1:对象.属性 // 固定属性访问
console.log( obj.uname ) // HiHi
// 语法2:对象['属性名'] // 动态属性访问
console.log( obj['age'] ) // 22

// 1.2 调用方法:
// 语法:对象.方法()
// console.log( obj.say ) // () => console.log('hello')
console.log( obj.say() ) // hello
  • 注意:
    1. 对象里的成员是无序的
8.1.2 构造函数创建对象
  • 构造函数:构造函数也是函数,只不过这个函数和new一起使用
  • Object:
  • 实例化对象: 就是 new 出来的对象
// 创建举例1:
let o = new Object()
// 添加成员
o.uname = 'Hi-Z' // 没有就添加
o.uname = 'Pi-M' // 有就修改
o.eat = () => console.log('吃饭中...')
o.say = () => console.log('说话中...')

// 创建举例2:
let o1 = new Object( {uname : 'haha', age : 22, sex : '男'} )
console.log( o1 )
  • 注意
    1. 如果不加参数,那么Object构造函数后面的小括号可以省略
    2. 构造函数建议首字母大写
8.1.3 自定义构造函数
  • 构造函数里的this指向当前实例对象
 function Person ( uname, age, sex ) {
   this.uname = uname
   this.age = age
   this.sex = sex
   this.say = () => {
     console.log( 'say方法' )
   }
   this.eat = () => {
     console.log( 'eat方法' )
   }
 }
// 实例化对象
let o1 = new Person( '阿飞', 18, '男' )
console.log( o1 ) // Person {uname: '阿飞', age: 18, sex: '男', say: ƒ, eat: ƒ}
let o2 = new Person( '假阿', 18, '女' )
console.log( o2 ); // Person {uname: '假阿', age: 18, sex: '女', say: ƒ, eat: ƒ}

8.2 遍历对象/遍历数组 - for in

// 遍历对象  for in
for ( let key in obj ) {
  // key: 代表对象里所有键
  // console.log( obj.key ) // 固定属性写法 都是undefined
  console.log( `${key}:${obj[key]}` ) // 动态属性写法
}

// 遍历数组  for in
let arr = [ 1, 3, 5, 7, 9 ]
for ( let i in arr ) {
  console.log( arr[i] )
}

8.3 构造函数-this指向

  1. 事件处理函数里的this指向事件源
  2. 箭头函数里的this指向父级的this指向
  3. 构造函数里的this指向的是当前实例对象(new 出来的对象叫实例对象)

8.4 new的执行

  • 执行过程
    1. 开辟空间
    2. this 指向这个函数
    3. 执行函数
    4. 返回这个对象
// 3. 执行函数
function Person ( uname, age ) {
  this.uname = uname
  this.age = age
  this.say = () => console.log('哇哈哈')
}
// 4.返回这个函数

// 1.开辟空间  2.this指向这个函数
let p1 = new Person( '张飞', 18 )
console.log( p1 )

8.5 构造函数-功能关键字

instanceof: 检测对象是否是某个构造函数的

constructor: 用来指回构造函数本身

function A () {}
function B () {}
// instanceof: 检测对象是否是某个构造函数的
// 语法:对象 instanceof 构造函数
let n = new B()
console.log( n instanceof A )
console.log( n instanceof B )
// constructor: 用来指回构造函数本身
// 语法:对象.constructor
console.log( n.constructor )

8.6 构造函数-成员

  • 静态成员:

    • 直接在函数身上的成员,称为静态成员

    • 只有构造函数才可以使用

  • 实例成员:

    • 函数内部给实例对象准备的成员,称为实例成员

    • 只有实例对象才可以使用

function Person (uname, age) {
  // 实例成员 (下三行)
  this.nuame = uname
  this.age = age
  this.say = function () {
    console.log('说话')
  }
}
// 实例化对象(p1)
let p1 = new Person('张飞', 22)
console.log( p1 )

// console.log( Person instanceof Object ) // true

// 静态成员 (下两行)
Person.language = '汉语'
Person.eat = function () {
  console.log('吃饭')
}

8.7 基本类型和引用类型的传递

  • 传递:
    • 值传递:把数据复制一份,传递 = 两份数据
    • 引用传递:把数据地址复制一份,传递 = 一份数据
let n = 1
let m = n // 基础类型传递的是值   复制值并传递
n = 2
console.log( n, m ) // 2 1

let o = {uname : '阿飞', age : 18}
let obj = o // 复杂类型传递的是地址  复制地址并传递
o.uname = '阿灰' // 因为地址相同,一变多变
console.log( o, obj ) // {uname: '阿灰', age: 18} {uname: '阿灰', age: 18}

9. 内置构造函数

引用类型:

  1. Object

  2. Array

  3. RegExp

包装类型:

  1. String

  2. Number

  3. Boolean

9.1 Object构造函数

Object构造函数的两个方法:

Object.keys: 获取对象所有键

Object.values: 获取对象所有值

  • Object: 是内置的一个构造函数
// 创建对象
// 字面量:{键值对}
let obj = {}
// 构造函数:Object
let o = new Object()

// 字面量创建obj1对象
let obj1 = {
  uname : '张三丰',
  age : 20,
  say : function () {
    console.log('say方法')
  }
}
// 静态方法
// Object.keys: 获取对象所有键
let re1 = Object.keys( obj1 )
console.log( re1 ) // ['uname', 'age', 'say']
// Object.values: 获取对象所有值
let re2 = Object.values( obj1 )
console.log( re2 ) // ['张三丰', 20, ƒ]

9.2 Array构造函数-方法

// 字面量:
let a = [1, 2, 3]
// Array: 构造函数,用于创建数组的构造函数
let arr = new Array('a', 'b', 'c')
console.log( a, arr) // [1, 2, 3] ['a', 'b', 'c']
  • 字面量创建数组,也就相当于 new 了一个实例对象
9.2.1 reverse - 反转

reverse: 反转数组顺序

  • 注意:会改变元数组

    let arr1 = ['a', 'b', 'c', 'd', 'e']
    let re1 = arr1.reverse()
    console.log( re1 ) // ['e', 'd', 'c', 'b', 'a']
    console.log( arr1 ) // ['e', 'd', 'c', 'b', 'a']
    
9.2.2 join - 拼接单元

join: 拼接数组的每个元素,拼接成为字符串

let arr2 = ['a', 'b', 'c', 1, 2, 3]
let re2 = arr2.join('') // 引号里可以填数组单元值之间用什么隔开
console.log( re2 ) // abc123
console.log( arr2 ) // ['a', 'b', 'c', 1, 2, 3]
9.2.3 concat - 拼接数组

concat: 把多个数组或者元素拼接成数组

let a1 = [1, 2, 3]
let b1 = ['a', 'b', 'c']
let c1 = [11, 22, 33]
let arr3 = a1.concat( b1, c1, '哇哈哈' )
console.log( arr3 )  // [1, 2, 3, 'a', 'b', 'c', 11, 22, 33, '哇哈哈']
9.2.4 inedxOf lastInedxOf

inedxOf: 查找某个元素在数组中首次出现的索引位置,

lastInedxOf: 查找某个元素在数组中最后一次出现的索引位置,

注意:如果找不到返回-1

let arr4 = ['a', 'b', 'c', 'd', 'a', 'b', 'c']
let re4 = arr4.indexOf('c')
let re44 = arr4.lastIndexOf('c')
console.log( re4 ) // 2
console.log( re44 ) // 6
9.2.5 Array.isArray() - 静态方法

Array.isArray(值): 判断是否数组

let n = 123
let nn = [1, 2, 3]
console.log( Array.isArray( n ) ) // false
console.log( Array.isArray( nn ) ) // true
9.2.6 Array.from() - 静态方法

Array.from(对象):把伪数组转换为真数组

注意:伪数组必须要有length属性

let o6 = {
  0 : 'a',
  1 : 'b',
  2 : 'c',
  3 : 'd',
  4 : 'e',
  5 : 'f',
  length : 6
}
let arr6 = Array.from( o6 )
console.log( arr6 ) // ['a', 'b', 'c', 'd', 'e', 'f']

9.3 Array构造函数-遍历方法

  • 语法

    // 数组.forEach( function ( item, index, o ) {
         // 第一个形参数:代表当前项
         // 第二个形参数:代表当前项的索引值
         // 第三个形参数:代表当前数组
    // } )
    
9.3.1 forEach - 遍历数组

forEach: 遍历数组

let arr = ['张飞', '关羽', 'blue', 'red', 1, 2, 3]
arr.forEach( (item, index, o ) => console.log(item, index, o) )
9.3.2 find - 遍历查找满足条件的第一个元素并返回

find: 遍历并查找满足条件的一个元素,并返回

let arr2 = [5, 3, 6, 8, 7, 9, 12, 2]
let re2 = arr2.find( (item) => {
  return item > 3
} )
console.log( re2 ) // 5
9.3.3 some - 遍历查找是否具有满足条件的元素,有一个即为 true

some: 遍历并查找是否具有满足条件的元素,有一个即为 true

let arr3 = [5, 3, 6, 8, 7, 9, 12, 2]
let re3 = arr3.some( (item, index, o) => {
  return item > 3
} )
console.log( re3 ) // true
9.3.4 every - 遍历并查找是否有满足条件的元素,都满足则为 true

every: 遍历并查找是否有满足条件的元素,都满足则为 true

let arr4 = [5, 3, 6, 8, 7, 9, 12, 2]
let re4 = arr4.every( (item) => {
  return item > 3
} )
console.log( re4 ) // false
9.3.5 filter - 遍历并筛选,把满足条件的值放到新的数组返回

filter: 遍历并筛选,把满足条件的值放到新的数组返回

let arr5 = [5, 3, 6, 8, 7, 9, 12, 2]
let re5 = arr5.filter( (item) => {
  return item % 2 === 0
} )
console.log( re5 ) // [6, 8, 12, 2]
9.3.6 map - 遍历并让每一个元素执行一遍回调函数,把结果放到数组中返回

map: 遍历并让每一个元素执行一遍回调函数,把结果放到数组中返回

let arr6 = [5, 3, 6, 8, 7, 9, 12, 2]
let re6 = arr6.map( (item) => {
  return item * item
} )
console.log( re6 ) // [25, 9, 36, 64, 49, 81, 144, 4]

9.4 RegExp构造函数

// RegExp: 是内置的一个构造函数【正则对象】
// 字面量创建:
let reg = /abc/
// 构造函数创建:
let reg = new RegExp(/abc/)

9.5 String构造函数-方法

// 字面量
let str = 'sadfdadfadfafadfa'
// 构造函数创建
let strr = new String('sadfdadfadfafadfa')
console.log( str, strr);

// 1. length: 字符串的长度,或字符串的个数
let str1 = 'sadfdadfadfafadfa'
console.log(str1.length) // 17

// 2. 索引值
let str2 = 'sadfdadfadfafadfa'
console.log(str1[0]) // s
// 可以循环遍历字符串每一位,不可以用forEach,因为是数组方法,for in 可以
for ( let i = 0; i < str.length; i++ ) {
  console.log( str[i] )
}
9.5.1 split - 分隔字符串为数组

split: 用于分隔字符串为数组

let str1 = 'abcdefabcder'
let re1 = str1.split('')
console.log(re1) // ['a', 'b', 'c', 'd', 'e', 'f', 'a', 'b', 'c', 'd', 'e', 'r']
9.5.2 indexOf lastindexOf

indexOf: 在字符串中查找某个字符,找到返回首次出现的索引值找不到返回-1

lastindexOf: 在字符串中查找某个字符,找到返回最后依次一次出现的索引值找不到返回-1

 let str2 = 'abcdefabcder'
 let re2 = str2.indexOf('c')
 console.log( re2 ); // 2
let str22 = 'abcdefabcder'
let re22 = str22.lastIndexOf('c')
console.log( re22 ); // 8
9.5.3 toLowerCase toUpperCase

toLowerCase: 转换为小写

toUpperCase: 转换为大写

let str3 = 'abcdEFGHABCabc'
let re3 = str3.toLowerCase( str3 )
console.log( re3 ) // abcdefghabcabc
let str33 = 'abcdEFGHABCabc'
let re33 = str33.toUpperCase( str33 )
console.log( re33 ) // ABCDEFGHABCABC
9.5.4 substring substr

substring(start, end): 截取字符串

substr(start, num): 截取字符串

  • substring(start, end): 截取字符串
    • 从索引值为start开始截取,截取到索引值位置为end的地方
    • 注意:不包含end索引位置上对应的字符
  • substr(start, num): 截取字符串
    • 从索引值为start开始截取,截取几位
    • 注意:不包含num索引位置上对应的字符
  • 注意:
    1. 不管是substring还是substr,截取字符串
    2. 如果只有一个参数,那么就是从这个字符串开始截取到最后
let str4 = 'abcdEFGHABCabc'
let re4 = str4.substring(3, 6)
console.log( re4 ) // dEF
let str44 = 'abcdEFGHABCabc'
let re44 = str44.substr(3, 6)
console.log( re44 ) // dEFGHA
9.5.5 trim: 去除字符串两端的空格

trim: 去除字符串两端的空格

let str5 = '  abcdEFG  HABCabc   '
let re5 = str5.trim( str5 )
console.log(re5) // abcdEFG  HABCabc
9.5.6 replace: 字符串替换

replace: 字符串替换

i: 全局 g: 不区分大小写

let str6 = 'abcaabbcc'
let re6 = str6.replace(/a/gi, 'A')
console.log( re6 ) // AbcAAbbcc

9.6 Number构造函数 - 方法

// 字面量
let n = 1
console.log( n ) // 1
// 构造函数创建
let m = new Number(123)
console.log( m ) // 123
9.6.1 toFixed: 保留两位有效数字

toFixed: 保留两位有效数字

  • 注意:该方法有四舍五入
let prive = 36.766161568
let re = prive.toFixed(2)
console.log( re ) // 36.77
9.6.2 parseInt parseFloat

parseInt: 取整

parseFloat: 取浮点数

  • 注意:ES6不让在全局用,归到Number构造函数下
let num = '156.682px'
let re2 = Number.parseInt( num )
console.log( re2 ) // 156
let re22 = Number.parseFloat( num )
console.log( re22 ) // 156.682

9.7 Boolean构造函数

// 字面量
let falg = true
console.log( falg )
// 构造函数
let f = new Boolean(true)
console.log( f )

// 万物皆对象
// 构造函数:let fun = new Function()
// function fun() {}

9.8 公共方法

9.8.1 toString - 转字符串

toString:转字符串

// 包装类型、引用类型 都可以用
// toString:转字符串
// 注意:undefined、null 不可以用这个方法,会报错
let num = 123
let arr = [1, 2, 3]
let re = num.toString()
console.log(re) // 123
let ree = arr.toString()
console.log(ree) // 1,2,3
9.8.2 强制转换

String:构造函数、强制转换

Boolean: 构造函数、强制转换

Number: 构造函数、强制转换

// undefined、null 转字符串
// String:构造函数、强制转换
console.log(String(null)) // null
console.log(String(undefined)) // undefined
// Boolean: 构造函数、强制转换
console.log(Boolean(null)) // false
console.log(Boolean(undefined)) // false
console.log(Boolean(123)) // true
// Number: 构造函数、强制转换
console.log(Number(null)) // 0
console.log(Number(undefined)) // NaN
console.log(Number("123")) // 123
9.8.3 valueOf: 获取原始值

valueOf: 获取原始值

//  valueOf: 获取原始值
let str = new String("abcdefg")
console.log(str.valueOf()) // abcdefg
let time = new Date()
console.log( time.valueOf() ) // 1649823350825(时间戳)

10. 封装

防止变量污染

10.1 命名空间封装

// let uname = '张三丰'
// let age = 22
// let emial = 'zsf@qq.com'

// let uname = 'Hi-ZZ'
// let age = 22
// let emial = 'Hi-ZZ@qq.com'

// 命名空间封装
// 字面量对象:把变量当作属性,把函数当作方法

let user1 = {
  uname : '张三丰',
  age : 22,
  emial : 'zsf3@qq.com'
}
let user2 = {
  uname : '张大丰',
  age : 28,
  emial : 'zsf1@qq.com'
}
let user3 = {
  uname : '张二丰',
  age : 25,
  emial : 'zsf2@qq.com'
}
console.log( user1.uname ) // 张三丰
console.log( user2.uname ) // 张大丰
console.log( user3.uname ) // 张二丰

10.2 构造函数封装

每构建一个实例化对象就会多一个公共方法,浪费空间

// 公共部分
// 姓名 性别 年龄 邮箱
function Person (uname, gender, age, email) {
  this.uname = uname
  this.gender = gender
  this.age = age
  this.email = email
  this.say = function () {
    console.log('你好啊')
  }
  this.eat = () => console.log('恰饭');
}
let o1 = new Person('张三', '男', '22', 'zsf@qq.com')
console.log( o1 )
let o2 = new Person('Hi', '男', 18, 'Hi@qq.com')
console.log( o2 )

11. 原型对象

prototype:指向构造函数的原型

constructor:指回构造函数本身

__proto__:用来指向原型对象

  • 原型对象:构造函数或函数的一个属性

    指向了一个对象,我们把这个对象成为原型,或原型对象

  • 每一个构造函数都有一个 prototype:指向构造函数的原型

  • 每个原型对象都有一个 constructor:指回构造函数本身

  • 作用:共享成员

function Person(uname, age) {
  this.uname = uname
  this.age = age
  // this.eat = function() {
  //   console.log('吃饭');
  // }
}
// 在构造函数的原型上添加方法
// 【原型对象上的方法构造函数的成员可以用】
Person.prototype.eat = function () {
  console.log("吃饭中...")
}
let o1 = new Person("张三", 18)
o1.eat() // 吃饭中...
let o2 = new Person("李四", 20)
let o3 = new Person("王五", 12)
  • 每个对象都有一个属性:__proto__
  • 作用:用来指向原型对象
  • 当一个对象,访问一个成员的,现在自身查找,如果查不到,沿着__proto__继续查找
  • 注意:__proto__是一个非标准属性
// 构造函数
function Person (uname, age) {
  this.uname = uname
  this.age = age
  this.langage = '汉语'
}
// 原型对象
Person.prototype.eat = function () {
  console.log('吃饭中...');
}
Person.prototype.head = 1
// 实例化对象
let obj = new Person('张三', 22)
console.log( obj.__proto__ === Person.prototype ) // true

11.1 原型对象 - 原理图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l6S3yYKC-1650621858212)(./images/YuanXing.png)]

12. 继承

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wgXOjDfj-1650621858215)(./images/JiCheng.png)]

12.1 原型继承

  • 继承: 第一步 把实例对象赋值给原型对象

    Chinese.prototype = new Person() // 继承

  • 继承 第二步 让原型上constructor指回自己的构造函数

    注意:原型上不存在 constructor, 因为覆盖问题

    Chinese.prototype.constructor = Chinese

// 公共构造函数
function Person() {
  this.head = 1
  this.legs = 2
  this.eyes = 2
  this.eat = function () {
    console.log('吃饭');
  }
  this.say = function () {
    console.log('say方法');
  }
}
// 单个构造函数
function Chinese () {
  this.language = '汉语'
  this.skin = '黄皮肤'
}
function Japanese () {
  this.language = '日语'
  this.skin = '黄皮肤'
}
function America () {
  this.language = '英语'
  this.skin = '白皮肤'
}

// 继承
// console.log( Chinese.prototype ) // 没继承前
// 继承 第一步 把实例对象赋值给原型对象
Chinese.prototype = new Person() // 继承
// 继承 第二步 让原型上constructor指回自己的构造函数
// 原型上不存在 constructor,  因为覆盖问题
Chinese.prototype.constructor = Chinese
// console.log( Chinese.prototype ) // 继承后

Japanese.prototype = new Person()
Japanese.prototype.constructor = Japanese

America.prototype = new Person()
America.prototype.constructor = America


// 实例化
let c = new Chinese()
console.log( c )
let j = new Japanese()
console.log( j )
let a = new America()
console.log( a )

12.2 原型链

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jB0cV2HA-1650621858217)(./images/YuanXingLian.png)]

function People () {
  this.head = 1
  this.legs = 2
}
function Chinese () {
  this.language = '汉语'
  this.skin = '黄皮肤'
}
// 继承
Chinese.prototype = new People()
Chinese.prototype.constructor = Chinese

let c1 = new Chinese()
console.log( c1 )
console.log(c1.constructor);

// 原型链上添加方法
Object.prototype.lanqiu = function () {
  console.log( '打篮球...' )
}
// 原型链上添加方法
People.prototype.lanqiu = function () {
  console.log( '...打篮球...' )
}

let c2 = new Chinese()
c2.lanqiu()  // ...打篮球...

13. this指向

  • 重点:谁调用,this指向谁】
  • 严格模式下普通函数this为undefined】
  • 箭头函数this之指向所在作用域的this;或者上级作用域的this
// 1. 普通函数
function fn() {
  console.log(this) // window、调用者
}
fn()
// 2. 事件处理函数
document.addEventListener("click", function () {
  console.log(this) // 事件源、调用者
})
// 3. 构造函数
function Person() {
  console.log(this) // 实例对象
}
new Person()
// 4. 方法
let obj = {
  uname: "张飞",
  fei: function () {
    console.log(this) // obj、调用者
  },
}
obj.fei()
// 5. 定时器
setTimeout(function () {
  console.log(this) // window、调用者
}, 1000)
// 6.
// 7. 箭头函数
let o = {
  uname: "阿飞",
  fei: function () {
    // console.log(this) // o
    // setTimeout( function () {
    //   console.log(this) // window
    // }, 1000)
    setTimeout( () => {
      console.log(this) // o
    }, 1000)
  }
}
o.fei()

14. 改变this指向 - call

  • call: 他是函数的一个方法
    • 语法:函数.call(this, 参数1, 参数2, …)

14.1 call - 函数的方法-改变this指向

// call: 他是函数的一个方法
// 语法:函数.call(this, 参数1, 参数2, ...)
// 执行过程:函数调用了call方法,call会回头执行函数,在执行函数的过程中this会指向call的第一个参数
// 使用场景:想改函数里this指向的时候
function fn(a, b) {
  console.log(this, a, b);
}
// fn()
let obj = {uname : '阿飞', age : 22}
// fn函数调用了call方法,call会回头执行fn函数,在执行函数的过程中this会指向call的第一个参数
fn.call(obj, 1, 2)

14.2 apply- 函数的方法-改变this指向

  • apply: 他是函数的一个方法
    • 语法:函数.call(this, 参数1, 参数2, …)
// 2. apply: 他是函数的一个方法
// 语法:函数.apply(this, [参数1, 参数2, ...])
// 执行过程:函数调用了apply方法,apply会回头执行函数,在执行函数的过程中this会指向apply的第一个参数
// 注意:apply的参数第一个是this的指向对象,第二个是一个数组,数组里面是任意个参数

// 使用场景:既要改变this指向,又要设计数组的时候
function fn2(a, b) {
  console.log(this);
  console.log(a, b);
}
let obj2 = {
  uname : '哇哈哈',
  age : 22
}
fn2.apply(obj2, [11, 22])

// 使用举例
let arr = [23, 25, 69, 84, 92, 62]
let re = Math.max.apply(null, arr)
console.log(re) // 92

// ...:剩余值(接收参数时)
// ...:扩展运算符(复杂值时)
console.log(...arr) // 23 25 69 84 92 62
let re2 = Math.max(...arr)
console.log(re2) // 92

14.3 bind - 函数的方法-改变this指向

  • bind: 他是函数的一个方法
    • 语法: 函数.bind(this, 参数1, 参数2, …)
// 3. bind: 他是函数的一个方法
// 语法: 函数.bind(this, 参数1, 参数2, ...)
// 执行过程:函数调用了bind方法,bind不会回头执行函数,而是悄悄改变了函数的this指向,然后返回新的函数
// 使用场景:需要改变this,但是不需要立马执行函数

function fn3(a, b) {
  console.log(this)
  console.log(a, b)
}
let o3 = { uname: "aaa" }
let re3 = fn3.bind(o3, 111, 222)
re3()

// 使用举例:
let btn = document.querySelector("input")
btn.addEventListener("click", function () {
  // 禁用元素
  this.disabled = true
  setTimeout(
    function () {
      // 启用元素
      this.disabled = false
    }.bind(this),3000) // 这里用call改变函数内this指向会回头立马执行函数;这行显示的this是事件源
})

15. 严格模式

  • 严格模式:严格
  • 开启严格模式:“use strict”
  • 放到哪个作用域哪个作用域就遵守严格模式
  • 注意:必须放到作用域的开头
// 开启严格模式后

// 变量必须生说明
// n = 1
// console.log( n ) // 报错

// 普通函数中的 this,不在指向window,而是undefined
function fn () {
  console.log(this) // undefined
}
fn()

// 函数形参不可以重名
// function fun(a, a) {
//   console.log(a + a) // 报错
// }
// fun()

16. 类 - class

16.1 类和对象

// ES6之前
// 模板:
// function Person () {}

// 人:泛泛
// 姚明: 高, 篮球, 有钱 

// ES6
// 类:泛泛概念
// 对象:具体概念

// 可以确定下来具体的东西是对象,确定不下来不够具体的是类

16.2 类的基本使用

  • 创建类:
    • 语法:class 类名 {}
    • 注意:类名首字母大写
  • 实例化:
    • 语法:new 类名()
// 创建类
class Person {}
// 实例化
let p1 = new Person()
console.log(p1);

// 检测实例化的对象是不是对象,是对象的话就是Object构造出来的
// console.log( p1 instanceof Object ) // true

// 练习创建类
class Dog {}
let hei = new Dog()
console.log(hei);

16.3 类的操作 - 添加成员 - static

添加成员:

  1. 实例成员 - 属性名 = 属性值
  2. 静态成员 - static

注意:方法直接自动添加到原型上了(Person.prototype)

// 1. 添加实例成员
// 创建类
class Person1 {
  // 实例属性 (定义变量不加let)
  uname = '张三丰'
  age = 22
  head = 1
  // 实例方法 (定义函数不加function)
  // 方法直接自动添加到原型上了(Person.prototype)
  eat () {
    console.log('eat');
  }
  say () {
    console.log('say');
  }
}
// 实例化
let o1 = new Person1()
console.log(o1);
// 2. 添加静态成员
// 创建类
class Person2 {
  // 静态属性
  static language = '汉语'
  static sjin = '黄皮肤'
  // 静态方法
  static sleep () {
    console.log('睡觉');
  }
  static walk () {
    console.log('走路');
  }
}
// 实例化
let o2 = new Person2()
console.log( o2 )
// console.log( o2.language ) // undefined
console.log( Person2.language ) // 汉语

16.4 类的操作 - 构造函数 - constructor () {}

构造函数、构造方法、构造器

constructor () {}

注意:

  1. 构造方法,在new的时候自动执行
  2. 构造方法,如果不写的话,那么内部会默认的添加上
  3. 构造方法,名字是固定的,不可以更改
  4. 构造方法,用来接收参数,做一些初始化的操作
  5. 一个类里面只能有一个构造方法,顺序无要求,建议写前面
// 创建类
class Person {
  head = 1
  constructor (uname, age, gender) {
    // 类里面固定的方法,用来接收参数,初始化操作,不可以改名
    this.uname = uname
    this.age = age
    this.gender = gender
  }

  say () {
    console.log('say')
  }
  eat () {
    console.log('eat')
  }
}

// 实例化 (注意方法在原型对象上)
let o1 = new Person('张飞', 22, '男')
console.log(o1) // Person {head: 1, uname: '张飞', age: 22, gender: '男'}

let o2 = new Person('关羽', 23, '男')
console.log(o2) // Person {head: 1, uname: '关羽', age: 23, gender: '男'}

let o3 = new Person('貂蝉', 21, '女')
console.log(o3) //  Person {head: 1, uname: '貂蝉', age: 21, gender: '女'}

16.5 类的操作 - 继承 - extends、super

extends: 申明一个类为子类

super: 调用父类的方法

class Father {
  constructor (uname, age) {
    this.uname = uname
    this.age = age
  }
  qian () {
    console.log('转它一个亿');
  }
}

// extends: 申明一个类为子类
// Son为子类,Father为父类
class Son extends Father {
  constructor ( uname, age, score ) {
    // 在继承时,如果子类有自己的constructor,那么必须使用super调用父类的方法
    // super: 调用父类的方法
    super(uname, age)
    this.score = score
    // 注意:必须先用super调用父级的构造方法,在用自己的构造方法
  }
  qian () {
    super.qian()
    // console.log('转它半个亿');
  }
}

// 实例化
let s1 = new Son('儿子', 2, 99)
console.log(s1) // Son {uname: '儿子', age: 2, score: 99}
s1.qian() // 赚它一个亿

16.6 类的本质

  • 类的本质:函数
    • 还是哪个构造函数function Person(){}
  • 语法糖、语法盐
    • i++ 是 i = i + 1 的语法糖
    • i = i + 1 是 i++ 的语法盐
// 构造函数
// function Person() {}
// let o = new Person()

// 类
class Person {}
let o = new Person()
// console.log( typeof Person ) // function
// console.log( Person.prototype )
// console.log( Person.__proto__ )

// 类的本质:函数
// 还是哪个构造函数function Person(){}

// 语法糖
// 语法盐
// 例:i = i + 1 和 i++
// i++ 是 i = i + 1 的语法糖
// i = i + 1 是 i++ 的语法盐

17. 拷贝

新对象 = JSON.parse( JSON.stringify(旧对象) )

17.1 拷贝-浅拷贝

let obj = {
  uname : '张三丰',
  age : 22,
  gender : '男',
  message : {
    index : 6,
    score : 99
  }
}
let newObj = {}
// 浅拷贝 有个方法 assign
// 语法:Objecy.assign( newObj, obj )
// Object.assign( newObj, obj )

// 浅拷贝-原理
// 遍历
// for ( let key in obj ) {
//   newObj[key] = obj[key]
// }

17.2 拷贝-深拷贝

// 封装深层拷贝函数
function kaobei(newObj, obj) {
  for (let key in obj) {
    // 必须先判断数组,因为数组也是对象,对象不是数组
    if (obj[key] instanceof Array) {
      // obj[key]可能是数组
      newObj[key] = []
      kaobei(newObj[key], obj[key])
    } else if (obj[key] instanceof Object) {
      // obj[key]可能是对象
      newObj[key] = {}
      kaobei(newObj[key], obj[key])
    } else {
      newObj[key] = obj[key]
    }
  }
}

let obj = {
  uname: "张三丰",
  age: 22,
  gender: "男",
  message: {
    index: 6,
    score: 99,
  },
}
let newObj = {}

kaobei(newObj, obj)

JavaScript 案例练习

1. 练习 - 数组去重

let arr = ['a', 'b','a', 'c','a', 'b','c', 'd']
let newArr = []
// 思路:依次获取每个元素,看看新数组里有没有,有就不管,没有就添加
for ( let i = 0; i < arr.length; i++ ) {
  if ( newArr.indexOf( arr[i] ) === -1 ) newArr.push( arr[i] )
}
console.log( newArr ) // ['a', 'b', 'c', 'd']

2. 练习 - 数组单元满足条件的返回

let arrr = [
  {gname : '华为', prive : '6000', num : 3},
  {gname : '三星', prive : '3666', num : 6},
  {gname : '苹果', prive : '11666', num : 9},
  {gname : '锤子', prive : '5888', num : 11}
]

let ree = arrr.filter( (item, index, o) => {
  return item.prive >= 5000 && item.prive <= 10000
} )
console.log( ree ) // 输出为下
// 0: {gname: '华为', prive: '6000', num: 3} 
// 1: {gname: '锤子', prive: '5888', num: 11}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值