JavaScript进阶

  • JavaScript进阶已关闭评论
  • 97 次浏览
  • A+
所属分类:Web前端
摘要

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。


闭包

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。在 JavaScript 中,闭包会随着函数的创建而被同时创建。

<body>   <script>     // 闭包 : 内层函数 + 外层函数变量     // function outer() {     //   const a = 1     //   function f() {     //     console.log(a)     //   }     //   f()     // }     // outer()      // 闭包的写法  统计函数的调用次数     function outer() {       let count = 0       function fn() {         count++         console.log(`函数被调用${count}次`)       }       return fn     }     const re = outer()     re() // 1     re() // 2   </script> </body> 

总结:

1.怎么理解闭包?

  • 闭包 = 内层函数 + 外层函数的变量

2.闭包的作用?

  • 封闭数据,实现数据私有,外部也可以访问函数内部的变量
  • 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来

3.闭包可能引起的问题?

  • 内存泄漏

函数

构造函数

构造函数是专门用于创建对象的函数,如果一个函数使用 new 关键字调用,那么这个函数就是构造函数。

注意事项:

  1. 使用 new 关键字调用函数的行为被称为实例化

  2. 实例化构造函数时没有参数时可以省略 ()

  3. 构造函数的返回值即为新创建的对象

  4. 构造函数内部的 return 返回的值无效!

  5. 构造函数的函数名一般是首字母大写(约定)

<body>   <script>     // 创建一个猪 构造函数      function Pig(uname, age) {       this.uname = uname       this.age = age     }     // console.log(new Pig('佩奇', 6))     // console.log(new Pig('乔治', 3))     const p = new Pig('佩奇', 6)     console.log(p)      function Goods(name, price, count) {       this.name = name       this.price = price       this.count = count       this.sayhi = function () { }     }     const mi = new Goods('小米', 1999, 20)     console.log(mi)     const hw = new Goods('华为', 3999, 59)     console.log(hw)     console.log(mi === hw) // false     mi.name = 'vivo'     console.log(mi)     console.log(hw)   </script> </body> 

函数参数

动态参数

arguments是一个伪数组,可以获取传递的实参。

<script>   // 求和函数,计算所有参数的和   function sum() {     // console.log(arguments)     let s = 0     for(let i = 0; i < arguments.length; i++) {       s += arguments[i]     }     console.log(s)   }   // 调用求和函数   sum(5, 10) // 15   sum(1, 2, 4) // 7 </script> 

剩余参数

剩余参数语法允许我们将一个不定数量的参数表示为一个数组。theArgs是一个真数组。

function(a, b, ...theArgs) {   // ... } 

说明:

  • a 和 b 分别接收第一个参数和第二个参数
  • 第三个参数以及后面的参数都由 theArgs 接收
  • 如果只有一个参数且为剩余参数,那么所有参数都由它进行接收
function sum(...theArgs) {   let total = 0;   for (const arg of theArgs) {     total += arg;   }   return total; }  console.log(sum(1, 2, 3)); // Expected output: 6  console.log(sum(1, 2, 3, 4)); // Expected output: 10 
展开运算符

...是展开运算符,可以展开数组。

<body>   <script>     const arr1 = [1, 2, 3]     // 展开运算符 可以展开数组     // console.log(...arr1) // 1 2 3      // console.log(Math.max(1, 2, 3))     // ...arr1  === 1,2,3     // 1. 求数组最大值/最小值     console.log(Math.max(...arr1)) // 3     console.log(Math.min(...arr1)) // 1     // 2. 合并数组     const arr2 = [3, 4, 5]     const arr = [...arr1, ...arr2]     console.log(arr) // [1,2,3,3,4,5]   </script> </body> 

箭头函数

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的thisargumentssupernew.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。

基础语法:

(param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression //相当于:(param1, param2, …, paramN) =>{ return expression; }  // 当只有一个参数时,圆括号是可选的: (singleParam) => { statements } singleParam => { statements }  // 没有参数的函数应该写成一对圆括号。 () => { statements } 

高级语法:

//加括号的函数体返回对象字面量表达式: params => ({foo: bar})  //支持剩余参数和默认参数 (param1, param2, ...rest) => { statements } (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }  //同样支持参数列表解构 let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; f();  // 6 

箭头函数中的 this

箭头函数中的 this 是从自己的作用域链的上一层继承的 this

<body>   <script>     // 以前 this 的指向:谁调用的这个函数,this 就指向谁     console.log(this)  // window     // 普通函数     // function fn() {     //   console.log(this)  // window     // }     // window.fn()     // 对象方法里面的 this     // const obj = {     //   name: 'andy',     //   sayHi: function () {     //     console.log(this)  // obj     //   }     // }     // obj.sayHi()      // 箭头函数的 this  是上一层作用域的 this 指向     // const fn = () => {     //   console.log(this)  // window     // }     // fn()     // 对象方法箭头函数 this     // const obj = {     //   uname: '张三',     //   sayHi: () => {     //     console.log(this)  // window     //   }     // }     // obj.sayHi()      const obj = {       uname: '李四',       sayHi: function () {         console.log(this)  // obj         let i = 10         const count = () => {           console.log(this)  // obj          }         count()       }     }     obj.sayHi()    </script> </body> 

解构赋值

解构赋值语法是一种 Javascript 表达式。可以将数组中的值或对象的属性取出,赋值给其他变量。

默认值

每个解构属性都可以有一个默认值。当属性不存在或值为 undefined 时,将使用默认值。如果属性的值为 null,则不使用它。

const [a = 1] = []; // a is 1 const { b = 2 } = { b: undefined }; // b is 2 const { c = 2 } = { c: null }; // c is null 

数组解构

基本变量赋值

const foo = ["one", "two", "three"];  const [red, yellow, green] = foo; console.log(red); // "one" console.log(yellow); // "two" console.log(green); // "three" 

解构比源更多的元素

在从赋值语句右侧指定的长度为 N 的数组解构的数组中,如果赋值语句左侧指定的变量数量大于 N,则只有前 N 个变量被赋值。其余变量的值将是未定义。

const foo = ["one", "two"];  const [red, yellow, green, blue] = foo; console.log(red); // "one" console.log(yellow); // "two" console.log(green); // undefined console.log(blue); //undefined 

交换变量

可以在一个解构表达式中交换两个变量的值。

let a = 1; let b = 3;  [a, b] = [b, a]; console.log(a); // 3 console.log(b); // 1  const arr = [1, 2, 3]; [arr[2], arr[1]] = [arr[1], arr[2]]; console.log(arr); // [1, 3, 2] 

忽略某些返回值

function f() {   return [1, 2, 3]; }  const [a, , b] = f(); console.log(a); // 1 console.log(b); // 3  const [c] = f(); console.log(c); // 1 

对象解构

基本赋值

const user = {   id: 42,   isVerified: true, }; // 变量名需要一致 const { id, isVerified } = user;  console.log(id); // 42 console.log(isVerified); // true 

赋值给新的变量名

可以从对象中提取属性,并将其赋值给名称与对象属性不同的变量。

const o = { p: 42, q: true }; const { p: foo, q: bar } = o;  console.log(foo); // 42 console.log(bar); // true 

举个例子,const { p: foo } = o 从对象 o 中获取名为 p 的属性,并将其赋值给名为 foo 的局部变量。

赋值到新的变量名并提供默认值

一个属性可以同时是两者:

  • 从对象提取并分配给具有不同名称的变量。
  • 指定一个默认值,以防获取的值为 undefined
const { a: aa = 10, b: bb = 5 } = { a: 3 };  console.log(aa); // 3 console.log(bb); // 5 

从作为函数参数传递的对象中提取属性

传递给函数参数的对象也可以提取到变量中,然后可以在函数体内访问这些变量。至于对象赋值,解构语法允许新变量具有与原始属性相同或不同的名称,并为原始对象未定义属性的情况分配默认值。

const user = {   id: 42,   displayName: "jdoe",   fullName: {     firstName: "Jane",     lastName: "Doe",   }, };  // 解构 function userId({ id }) {   return id; } console.log(userId(user)); // 42  // 解构并重命名 function userDisplayName({ displayName: dname }) {   return dname; } console.log(userDisplayName(user)); // `jdoe`  // 解构嵌套对象 function whois({ displayName, fullName: { firstName: name } }) {   return `${displayName} is ${name}`; } console.log(whois(user)); // "jdoe is Jane" 

数组

forEach 遍历数组

<body>   <script>     // forEach 就是遍历  加强版的for循环  适合于遍历数组对象     const arr = ['red', 'green', 'pink']     arr.forEach(function (item, index) {       console.log(item)  // 数组元素 red green pink       console.log(index) // 索引号     })   </script> </body> 

filter 过滤元素

const words = ['spray', 'elite', 'exuberant', 'destruction', 'present'];  const result = words.filter((word) => word.length > 6);  console.log(result); // Expected output: Array ["exuberant", "destruction", "present"]