JS avanzado relacionado

JSCore01

la tercera fase

  • JS avanzado --- Las habilidades básicas de JS que se investigarán durante la entrevista están todas aquí (extremadamente difícil)

    • Habilidades de estudio: concéntrese en comprender, no lea ni escriba

  • DOM: una tecnología para manipular de forma flexible HTML+CSS con JS

    • puede hacer que las páginas web cambien

    • Habilidades de aprendizaje: escribir más y practicar más

  • jQuery

  • vista

impulso de declaración

Etapa de profesor de Liangliang: las variables declaradas por var tienen promoción de declaración

Una característica del lenguaje que debe conocerse al aprender el lenguaje JS: las características de 其他los lenguajes de programación没有

¿Por qué otros idiomas no tienen esta característica?Porque esta característica es especial垃圾

Cuando se ejecuta el lenguaje JS, el código real se ejecuta dos veces.

  • Primera vez: primero busque todas las operaciones de declaración ( var/function/let/const/class), extraiga hacia arriba

  • Segunda vez: Ejecute el código elevado nuevamente

Preguntas frecuentes en las entrevistas:考察你的JS基础如何!

En JS: ver no es necesariamente creer, la capa inferior actualizará implícitamente el código 提升primero执行

 

Tanto var como function son declaraciones, ¿cuál viene primero?

  • El autor de JS nunca ha dicho claramente quién viene primero

  • Pero el orden no es importante.

    • Cuando se promueva la función, se llevará el cuerpo de la función

    • Cuando se eleva var, solo se elevan las declaraciones de variables sin valores

    • Independientemente de quién escribe primero y quién escribe después, el valor promocionado es una función

      function a(){}
      var a
      ​
      var b 
      function b(){}

alcance

Un alcance es un nombre para una clase de tipos de objetos que tienen operaciones especiales

  • global

  • local/función

  • nivel de bloque

  • guión

Entorno de alojamiento: en qué plataforma se ejecuta JS, esta plataforma se denomina entorno de alojamiento de JS

  • node.js: operar base de datos/solicitud de red/operar sistema de archivos...

  • Navegador: proporciona información relacionada con el navegador.技能包

    • almacenado en el objeto ventana, que también se conoce como全局作用域

    • Porque var/functionlas variables declaradas con se almacenarán automáticamente en la ventana

var tiene 全局变量污染características:

  • Globales: ventana

  • La variable declarada por var se almacenará automáticamente en la ventana, ¡contaminando la estructura original de la ventana!

alcance de la función

Cuando la función está en 运行, automáticamente creará una 对象para guardar 函数中la variable declarada

Este objeto especial se llama: el alcance de la función también se llama 局部alcance

El ámbito local y el ámbito global son independientes y no se afectan entre sí

Dado que el objeto de ámbito se crea cuando se ejecuta la función, después de que se ejecute la función,自动销毁

Por lo tanto, debe usar 断点调试la función para ver este objeto de alcance especial

ámbito de la secuencia de comandos

alcance del bloque

cadena de alcance

Cierre

El cierre es un alias para el alcance de la función.

Cuando nace una función, guardará automáticamente su ubicación 词法作用域(ámbitos)

Almacenado en el scopesatributo de la función.

¿Por qué ahorrar?以后函数不管在哪里使用, 永远都是曾经的少年--携带固有属性

Estos alcances inherentes, 函数作用域conocidos como闭包

Cuando escuche 闭包este nombre: debe saber que se trata de un ámbito de función que se almacena en los ámbitos de otra función

  • Por ejemplo, en el caso, cla función bse declara en la función y bel alcance de la función se guarda en celscopes

    En este momento, bel alcance de la función es cel cierre de la función.

Revisión de contenido de hoy

JS avanzado: comprenda la esencia de JS, el diseño subyacente, requerido para las entrevistas

  • impulso de declaración

    • Funciones exclusivas del lenguaje JS, que no se encuentran en otros lenguajes: este diseño es particularmente

    • Cuando el código JS se está ejecutando, la estructura del código se ajustará primero y luego se ejecutará.

    • Levante la operación de declaración ( var/function/let/const) a la parte superior del alcance antes de ejecutar

    • 注意: Lea el código JS 千万不要en el orden de las personas normales从上到下

  • alcance

    • La esencia del alcance es una variable de tipo de objeto, solo porque este tipo de objeto es especial

    • ventana: el tipo de objeto proporcionado por el navegador, que almacena todos los códigos de función del navegador. Se denomina objeto global.

      • Las variables declaradas usando var y función se almacenan automáticamente en la ventana

    • Ámbito local: cuando se llama a la función, generará automáticamente un tipo de objeto para almacenar las variables declaradas en la función, que se ejecutará cuando se ejecute la función 完毕.自动销毁

    • Alcance del script: a partir de ES6 2015, use let /const / classel declarado en el script y guárdelo en el área del script

    • Nivel de bloque: a partir de ES6 2015, las variables declaradas {}con let/const/classla palabra clave in se almacenan en el objeto de ámbito de nivel de bloque.

  • cadena de alcance

    • De acuerdo con la escritura del código, cuando se usa una variable en una función, primero se busca desde su propio ámbito, y si no se tiene a sí misma, se busca 上层en el ámbito, hasta que se encuentra la ubicación (principio de proximidad). )

  • Cierre

    • Cuando se declara la función, guardará su ubicación 词法环境(所有父作用域)en el atributo scopes

    • Si es el alcance de la función, se llama un cierre.

    • Comprensión simple y aproximada: la función externa es el cierre de la función interna; debe ser la forma de anidar la función

    • Desventajas: Desperdicio de memoria.El alcance de la función externa no se destruirá automáticamente, lo guardará la función interna.

    • Función: Antes de ES6 2015, utilizado para evitar la contaminación variable global.

      • Use cierres para proporcionar variables privadas para funciones para evitar la contaminación de variables globales

codigo del dia

impulso de declaración

<!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>声明提升</title>
</head>
<body>
<!-- HTML中, 有两个特殊的标签 -->
<!-- style: 其中用于书写 css 代码 -->
<!-- script: 其中用于书写 JavaScript 代码 -->
<script>
// function: 用于声明函数
// 函数就是把 一段代码保存起来, 起了个名字
// 注意: 函数必须调用之后, 才能执行{}中的代码
// 调用函数的格式: 函数名(). 通过()来触发
// JS的反人类设计: 不能按照正常人的阅读顺序来理解代码
// 你所见到的 并非 JS 实际运行时的模样
// 因为JS拥有: 声明提升的机制
// 声明: 制作出来一个变量 就叫声明 -- 变量出生的时候
// 用于声明变量的关键词: var/function + let/const/class
a()
function a(){
console.log(111)
 }
var a //声明了变量a
var b //声明了变量b
function c(){} //声明了函数c
</script>
<script>
// 在阅读JS代码时, 一定不要当正常人
// 正常人: 从上向下阅读
// JS具有声明提升特征: 先隐式调整代码的顺序, 然后再执行
function b(){
console.log(111)
 }
b()
function b(){
console.log(222)
 }
b()
</script>
</body>
</html>

 poca practica

​
<!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>
  <script>
    a()
​
    function a() {
      console.log(111);
    }
​
    function a() {
      console.log(222);
    }
    a()
​
    a = function () { console.log(333) }
    a()
  </script>
</body>
​
</html>
<!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>
  <script>
    // = :称为赋值符号. 把一个值保存到一个变量里
    // 如果变量中 已经有值了 会怎样,  旧的会清理掉, 换成新的
    var a = 5
    var a = 8
    console.log(a);
​
    function b() { }
    console.log(b);
​
    b = 666
    console.log(b);
​
​
​
​
    // 函数作为 表达式的一部分, 称为函数表达式
    // 表达式中的函数: 不会提升
    b = function () { console.log(222); }
    console.log(b);
​
    // 整个表达式 就是一个函数, 可以提升
    function c() { }
  </script>
​
  <script>
    console.log('-------------------------');
​
    ff = function () { console.log(222); }
    ff()
​
    function ff() {
      console.log(1111);
    }
    ff()
​
​
​
  </script>
</body>
​
</html>
<!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>
  <script>
    // 此处是合写格式
    // var a;  a = 5;
    var a = 5
​
    function a() {
      console.log(111);
    }
​
    console.log(a);
  </script>
</body>
​
</html>
​
<!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>
  <script>
    // 为一个变量重新赋值, 只能用 = 进行
    function a() { }
    // 声明a, 如果a中没有值, 就是undefined
    // 而不是: 声明a的同时 赋值成 undefined
​
    // 但是 a 中存储了函数, 所以a的值就是函数
    var a  //这是赋值吗?? 不是!!!  声明操作
​
​
    // 没有 = 就不会给a赋值
​
​
    console.log(a);
  </script>
</body>
​
</html>

alcance

<!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>作用域</title>
</head>
​
<body>
  <script>
    // JS有4种作用域: 全局 函数 脚本 块级
    // 专业名词: 宿主环境 -- 被寄生的就叫宿主
    // JS语言有两种常见的宿主: node.js 和 浏览器
    // JS寄生在宿主上之后, 就可以使用宿主的各种功能
    // JS寄生在浏览器上时, 就拥有了操作浏览器的各种技能
    // 这些技能存储在 浏览器提供的 window 对象属性中
    console.log(window);
    console.log(typeof window); // object:对象类型
​
    // 作用域 就是 一个特殊的对象类型的值
    // window对象,就是浏览器提供的全局作用域
    // 使用 var 在脚本中声明的变量, 就会存储在全局作用域 window对象里
    var aa = 'AAA'
​
    function aab() { }
​
    // 用法1: 读取 全局作用域 window对象中的值
    console.log(window.aa);
    // 用法2: 直接用变量, 默认会从全局作用域获取
    console.log(aa);
  </script>
</body>
​
</html>

ámbito local

<!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>局部作用域</title>
</head>
​
<body>
  <script>
    // 2015年之前, 即ES6 -- JS的第六次升级版本 前
    // 只有两种作用域: 全局 , 局部(函数)
    function a() {
      var x = 11
      var y = 22
      var z = 33
      console.log(x, y, z);
    }
    // 注意: 函数需要调用才能触发
    // 调用时, 会触发 {} 中的代码, 并制作一个 局部作用域--对象类型
    // 需要浏览器提供的 断掉调试 软件, 来查看函数运行时的作用域
    a()
  </script>
</body>
​
</html>

ámbito de la secuencia de comandos

<!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>脚本作用域</title>
</head>

<body>
  <!-- 
    由于 var 在 script 中声明的变量, 自动出现在 window 对象里,
    而 window 对象是浏览器提供的 用于存储 系统方法 的对象

    把自定义的变量存储在 window 中, 会造成全局变量污染
    所在 从 2015年开始 的 第六个JS版本, 称为 ES6 
    提供了新的脚本作用域, 专门存储 自定义的 变量
  -->
  <script>
    // var在 script 声明的变量, 存储在 window 对象里
    // 和系统提供的内容 混合在一起: 全局变量污染
    var aa = 'AAA'

    // let/const : ES6中提供的 声明变量的 关键词
    // 在 script 中声明的变量, 存储在 script 对象里 而非 window
    // 避免的全局变量污染
    let bb = 'BBB'

    // 取舍:
    // 理论上: 推荐用 let/const 代替 var  -- var就特性,被淘汰!
    // 实际上: 为了兼容性的考虑, 对于2015年之前的浏览器--IE8
    //        -- 有些政府项目中, 要考虑适配 旧版本浏览器, 只能用var

    console.log('-----');
  </script>
</body>

</html>

alcance del bloque

<!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>块级作用域</title>
</head>

<body>
  <script>
    // 块级: 由 ES6 中提供的作用域, 类似 局部作用域
    // {} 配合 let/const 使用, 就会生成独立的块级作用域对象
    // 但是 var 对块级无效, 依然在全局中

    // 代码中: if  for while switch 都有 {}, 会产生块级
    {
      let a = 5
      const b = 6
      var c = 7
      console.log('....');
    }

    function d() {
      // 函数的{} 不会产生块
      // 依然是 函数作用域
      let a

      {
        // 依然形成块级作用域
        let b
        console.log(b);
      }

      console.log(a);
    }

    d()
  </script>
</body>

</html>

cadena de alcance

<!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>作用域链</title>
</head>

<body>
  <script>
    // JS中, 代码结尾的分号 非必备, 是可选的
    // 由于大家越来越懒.. 现在很多人习惯不写 分号

    // undefined: 声明了但是没赋值
    // undeclare: a is not defined 代表变量不存在, 即没声明

    // 当使用一个变量时, 会按照就近原则, 到作用域链中查找并使用
    // 细节: 查找时 向上层作用有中查找
    // 找祖宗 不找 儿子
    var a = 11

    function b() {
      var a = 22;

      // 函数的自调用  (function(){})()
      // 细节: 自调用写法 和 上一行代码之间 必须有 分号 间隔
      (function () {
        var a = 33

        function c() {
          var a = 44
        }
        c()

        // 如果 a = 33 不写, 会到上层作用域中查找
        // 不会到 c 中查找
        console.log(a) //??
      })()
    }
    b()
  </script>
</body>

</html>

entrenamiento combinado

<!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>综合练习</title>
</head>

<body>
  <!-- 声明提升: JS独有的特征, 先隐式调整代码的结构, 把 声明操作 var/function 提升到作用域的顶部, 然后再运行 -->

  <!-- 作用域: 一些特殊的对象.  window全局  函数触发后-局部 -->

  <!-- 作用域链: 使用一个变量时, 就近原则 从自身向上层作用域查找 -->

  <script>
    var a = 10

    function b() {
      a = 20
      console.log(a);
    }
    b()

    console.log(a);
  </script>

  <script>
    // 代码提升后的样子如下:
    function b() {
      // 变量a在哪??   函数自身没有用 var 声明变量a
      // 所以 到上层作用域中查找: 找到了window中的a
      a = 20 // 把 a 的值替换成 20
      console.log(a) // 打印出20
    }
    // var a = 10
    var a


    //
    a = 10
    b() //触发函数体中的代码
    console.log(a);
  </script>
</body>

</html>
<!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>综合练习</title>
</head>

<body>
  <script>
    var a = 10

    function b() {
      // var: 用于在当前作用域中声明变量
      // 当前在函数作用域中, 所以声明了变量a
      // var a = 20
      var a
      // 因为当前作用域中有 a , 所以就给当前作用域的a赋值
      a = 20
      console.log(a) //20
    }

    b()
    console.log(a);
  </script>
</body>

</html>

<!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>综合练习</title>
</head>

<body>
  <script>
    var a = 10

    function b() {
      // 考点: 声明提升;  var a 实际运行时会先提升到作用域的顶部
      // var a
      a = 20
      console.log(a);
      var a
    }

    b()
    console.log(a);
  </script>
</body>

</html>

función de cierre

<!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>闭包特征</title>
</head>

<body>
  <script>
    // 类似: 亮亮出生时 在 成家, 所以姓成
    // 如果亮亮以后 入赘到 涛哥家里.. 是否依然姓成?
    // 答案: 依然是,  出生时就锁死. 携带在自身的固有属性

    // 函数 在声明时, 即 function 书写时, 就已经把自身要用到的各种变量 都携带在身上, 不管以后在哪里使用, 都是固有的属性

    // scope: 作用域  scopes:作用域们
    // 函数的 scopes 属性中, 存储来函数 出生时, 所在的作用域们
    // closure: 闭包 -- 函数作用域的别名
    // global: 全局

    var a = 10

    function b() {
      var a = 20

      // c出生时: 在b作用域中, b出生时在全局里
      function c() {
        // 这里的a ,根据作用域链的元素, 使用 b函数作用域中的a
        // 但是 把 c 作为返回值, 传递到外部, 为什么依然能打印出a?
        console.log(a) //打印出什么?
      }

      return c // 返回c函数
    }

    var c = b() // b的返回值, 存储在 变量c 中
    console.log(c);

    c() // 触发全局中的c函数 打印出什么?

    // 打印有很多种方式, 最常见:log --具有美化功能
    // console.log(c);

    // dir: direct直接, 输入函数原本的模样
    console.dir(c);
  </script>
</body>

</html>
<!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>闭包特征</title>
</head>

<body>
  <!-- 
    JS的固有设定: 函数在出生时 会保存 其所在的所有作用域 到 函数的scopes 属性里

    例如: 亮亮老师在出生的时候, 就会保存: 爸爸是谁,妈妈是谁, 爷爷奶奶, 姥爷姥姥 , 北京的5套房子.  永远都携带在身上
   -->

  <script>
    {
      // let 配合 {} 会形成块级作用域
      let a = 10
      // alt+上/下 : 移动当前行

      // 把函数c 放在另一个函数中声明
      function b() {
        var x = 999

        // b函数作用域 是 c函数的闭包, 存储在 c的 scopes 属性里
        function c() {
          // 细节: 函数只存对自身有用的, 
          // 如果没有使用变量a, 则不会存储a 所在的作用域
          console.log(a, x)
        }

        console.dir(c) //利用dir 直接查看函数本体, 展开查看 scopes 属性
      }
      b()
    }
  </script>
</body>

</html>
<!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>闭包特性</title>
</head>

<body>
  <!-- 
    闭包: 函数在声明时, 会保存其所在的所有作用域 到 scopes 属性里, 如果这个作用域 是个函数作用域, 称为 闭包Closure

    粗暴理解: 函数保存所有的父元素到自身的scopes属性里

    闭包的形成: 必须是 函数中声明另一个函数

    外层的函数  是 内层函数的 闭包
   -->
  <script>
    // Closure:闭包
    (function () {
      var a = 10

      // 声明函数, 
      function b() { console.log(a) }
      // b的scopes属性中存储了 b函数声明时所在的作用域们 (祖先们)
      // 匿名函数作用域 被保存在 b 的scopes 中,  称为 b的闭包
      // 本质上 闭包就是函数作用域, 只是因为被b存储了, 所以称为闭包

      // 例如: 迪丽热巴.   假如 嫁给了家乐,  称为 家乐的妻子
      // 迪丽热巴 别名是 妻子.  说明是别人的妻子
      console.dir(b)
    })()
  </script>
</body>

</html>

Acerca de las funciones

<!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>关于函数</title>
</head>

<body>
  <script>
    // 关于函数: 分两种状态 -- 静态  动态

    // 静态的: 制作了一个函数
    function b() {
      // return 返回结果
      // 不写return 则默认是 undefined
      // return 111
    }

    // 打印静态的函数
    console.log(b);

    // 动态: 利用()触发; 打印函数运行后的
    console.log(b());
  </script>
</body>

</html>

Aplicación de cierres

<!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>闭包的应用</title>
</head>

<body>
  <!-- 
    闭包的设计的缺点:
    - 正常 函数执行时 会形成 局部作用域对象, 当函数执行结束时, 这个对象会销毁, 来节省内存
    - 但是: 闭包机制会导致 函数作用域 被保存到另一个函数中, 无法释放. 导致内存的浪费

    所以: 在ES6中, 提供了 块级作用域的写法, 来代替闭包

    由于兼容性 和 习惯: 闭包依然非常常见
   -->

  <script>
    // 闭包作用: 为函数提供私有变量, 避免全局污染 -- ES6之前

    // 例如: 记录一个函数的调用次数
    // var声明的变量, 存储在 window 全局中: 污染全局变量
    // 如何避免全局污染??  let/const -- ES6  2015年出现
    // 2015年之前 靠什么?  需要闭包 -- 提供一个函数作用域来存储变量
    console.log(window);

    // 习惯使用匿名函数自调用, 来提供一个函数作用域
    // 声明变量, 保存函数的返回值; 此时就可以在外部使用b
    var b = (function () {
      // 在匿名函数作用域中, 声明变量: 不在全局区 就没有全局污染
      var count = 0

      function b() {
        // var count = 0
        count++
        console.log('调用了第' + count + '次');
      }
      // 通过return 把b暴露到外部  -- return 大腰子
      return b
    })()

    // 目的是:让count变成私有的, 避免全局污染
    console.dir(b) // 查看 count 是不是存在 scopes 里

    b()
    b()
    b()
    b()
  </script>
</body>

</html>

JSCORE02

Parte avanzada de JS: enfoque en la comprensión

revisar

La parte avanzada de JS explica principalmente: el concepto de diseño de la capa inferior de JS --面试必考

  • impulso de declaración

    • La forma en que se ejecuta realmente el lenguaje JavaScript:不要看表面

    • Cuando el código JS se está ejecutando realmente, 隐式la estructura del código se ajustará primero y luego se ejecutará el código ajustado:如果按照代码从上向下阅读, 并不准确

    • 声明El código de la operación se eleva a la parte superior de su alcance antes de ejecutarse

      • Declarar operaciones:var/function/let/const/class

    • Puntos de prueba: el código JS que se ejecuta no es el mismo que ve, y la estructura se ajusta implícitamente

  • alcance

    • El alcance es esencialmente una 对象类型variable, solo porque este tipo de objeto tiene funciones especiales

    • 4 objetos de alcance

      • Objeto de alcance global: cuando se usa el navegador 宿主环境, es la propiedad de la ventana

        • varLas variables declaradas en el script se almacenan en la ventana, por lo que hay全局变量污染

      • Objeto de alcance local: 触发Cuando se ejecuta la función, se generará un objeto 临时para almacenar las variables declaradas en la función.Al final de la ejecución de la función,自动销毁

      • Objetos del alcance del script: variables declaradas en el script ES6 2015 JS的第6个版本usando la palabra clavelet/const

      • Alcance a nivel de bloque: cuando se usan {}juntos let/const, se formará un alcance a nivel de bloque

        • If/for/switch/while all have {} para formar un ámbito de nivel de bloque

  • cadena de alcance

    • De acuerdo a la posición de escritura del código, cuando se usa una variable en una función, primero se buscará 自身作用域en ella, y si no existe, se buscará 上级作用域en --就近原则

  • Cierre

    • Cuando se declara una función, guardará su ubicación 词法作用域en su propio atributo de ámbito. Si el ámbito léxico es 函数作用域, se denomina cierre.

      • 词法作用域Hay 4 categorías: global, script, nivel de bloque,闭包(局部作用域/函数作用域)

      • La esencia del cierre es de alcance local, pero en el panorama actual se llama cierre.

      • Formación de cierre: la función interna debe declararse en la función externa, y la función externa es el cierre de la función interna en este momento

      • Desventajas de los cierres: originalmente, el alcance de la función se destruirá automáticamente, pero debido a la operación de cierre, ya no se destruirá automáticamente, ¡desperdiciando memoria!

      • La función se divide en dos estados: estático y dinámico.

        • Estático: declarar funciones: los cierres se almacenan en funciones estáticas

        • Dinámico: llame a la función: el valor en el cierre se usará al ejecutar

    • El papel del cierre:

      • Antes ES6, solo había dos ámbitos: global/local (función)

      • Las variables declaradas por var se almacenan globalmente, lo que provoca contaminación de variables globales

      • 闭包: Las variables se pueden declarar en el alcance de la función para evitar la contaminación de variables globales

        • producción 私有的变量, para evitar la contaminación variable global

argumentos

<!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>函数的arguments</title>
</head>
​
<body>
  <script>
    // 计算任意数量 参数的和
    function add() {
      // 函数隐式带有一个 arguments 属性, 其中存储了函数收到的所有参数
      // 通过打印可以发现: arguments 是个对象类型
      // 只是属性名是 0 1 2 3 ...  跟数组相似而已
      // 我们称这种样子的对象: 伪数组/ 类(似)数组
      // 像数组 但是没有数组的各种方法  -- 太监 - 像男人..但是不行
      console.log('arguments:', arguments);
​
      var sum = 0
​
      for (var i = 0; i < arguments.length; i++) {
        var value = arguments[i] //下标取值
        sum += value //累加到sum上  sum = sum + value
      }
      console.log(sum);
    }
​
    add(10, 20)
    add(100, 200, 10, 20)
    add(100, 200, 10, 20, 40, 50)
  </script>
</body>
​
</html>

sobrecarga de funciones

Una técnica para hacer funciones: puede hacer que una función tenga más funciones y sea más poderosa

Ejecute diferentes códigos lógicos juzgando el número o tipo de parámetros

El método de implementación específico:

  • El atributo arguments que viene con la función dependiente: almacenar todos los parámetros recibidos por la función

  • Use argumentos para determinar la cantidad de parámetros que acepta una función

  • O lea los parámetros de los argumentos para determinar su tipo

<!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>函数的重载 10:07</title>
</head>
​
<body>
  <!-- 函数的重载: 通过判断参数的 数量 或 类型 来执行不同的逻辑代码 -->
  <!-- 优点: 让一个函数具有多种作用, 功能更加强大 -->
​
  <!-- 具体实现方式: 利用 arguments 属性, 来读取参数的个数 或者 某个参数的类型, 通过if判断来执行不同的逻辑代码 -->
​
  <script>
    // 参数是数字类型, 当做时间戳(距离1970年1月1日的秒数)来识别
    // 系统提供的 Date, 其会根据参数的类型不同, 用不同的方式进行转换, 最终得到时间
    var t = new Date(1453243343453)
    console.log(t);
​
    var t = new Date('2020/10/20')
    console.log(t);
​
    // 制作一个求和的函数, 两种作用: 求出多个参数的和 或 数组的和
    function add() {
      // 参数的个数如果是1个 且 是数组类型
      // console.log(arguments);
      // Array.isArray(): 判断值是否为数组类型
      if (arguments.length == 1 && Array.isArray(arguments[0])) {
        // arguments = { 0: [11, 22, 33, 44, 66] }
        var nums = arguments[0]
        // nums = [11, 22, 33, 44, 66]
​
        var sum = 0
        // 数组.length: 获取数组的长度
        for (var i = 0; i < nums.length; i++) {
          sum += nums[i]
        }
        console.log(sum);
      } else {
        // 否则: 一堆数字的场景
        // 例如 arguments: {0: 10, 1: 20, 2: 30,  3: 40, length: 4}
        var sum = 0
        for (var i = 0; i < arguments.length; i++) {
          sum += arguments[i]
        }
        console.log(sum);
      }
    }
​
    // add: 可以传递一堆数字 或 传递 一个数组
    add(10)
    add(10, 20, 30, 40)
    add(10, 20, 30, 40, 6, 7, 8)
​
    add([11, 22, 33, 44, 66])
  </script>
​
  <script>
    // 练习: 制作一个函数, 计算出数字的累加之和
    function getSum() {
      console.log(arguments);
      // arguments: 接受到的参数们
      if (arguments.length == 1) {
        var sum = 0
        // 看下成亮老师讲解的 对象的 下标取值 -- 对象访问器语法
        for (var i = 1; i <= arguments[0]; i++) {
          sum += i
        }
        console.log(sum);
      }
​
      if (arguments.length == 2) {
        var sum = 0
        for (var i = arguments[0]; i <= arguments[1]; i++) {
          sum += i
        }
        console.log(sum);
      }
​
      if (arguments.length == 3) {
        var sum = 0
        for (var i = arguments[0]; i <= arguments[1]; i += arguments[2]) {
          sum += i
        }
        console.log(sum);
      }
    }
​
    // 升级: 如果3个参数, 第三参数代表步长 50 52 54 56... 间隔2
    getSum(50, 200, 2)
    getSum(50, 200, 3)
​
    // 例如:
    getSum(100) //累加出 1 - 100 之间数字的总和
​
    getSum(50, 150) // 累加出 50 - 150 之间的数字总和
​
    getSum(150, 10)
  </script>
</body>
​
</html>

Parte de la función - operación avanzada

  • Alcance de la función: los objetos creados automáticamente cuando se activa una función se utilizan para almacenar variables declaradas en la función

  • Cadena de alcance: para las variables utilizadas en funciones, use primero su propio alcance y, si no los tiene, vaya a la capa superior para encontrarlos.

  • Cierre: cuando se declara la función, 作用域们guarde su ubicación en el atributo de ámbitos

    • Entre los alcances: el alcance de la función se llama cierre.

  • La función tiene implícitamente la propiedad arguments: almacena 接受todo lo que pertenece a la función 实参, como (como) un tipo de matriz.Como una matriz pero sin varios métodos de una matriz -- eunuco: como un hombre, pero...

  • Sobrecarga de función de habilidad: ejecute diferentes códigos lógicos juzgando el número o tipo de parámetros de la función

    • Implementación específica: confíe en el atributo arguments para realizar

accesor de propiedad

<!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>对象的访问器语法</title>
</head>
​
<body>
  <script>
    // 对象的访问器语法
    // JS官方文档: MDN  - https://developer.mozilla.org/zh-CN/
​
    // JS提供了两种 属性访问器 语法,  分别是 点号 和 方括号
    var emp = { ename: 'mike', age: 19, 1: 'one' }
    console.log(emp);
​
    // 读取ename属性的值
    console.log(emp.ename) //点语法读取
    console.log(emp['ename']) //方括号语法
​
    // 如何读取 属性1 的值
    // console.log(emp.1); // .1 是小数的表达方式  11.2
    console.log(emp[1]); // 数字只能用 方括号语法
​
    // 错误理解: []下标取值 是数组特有的语法!
    // 正确理解: 由于数组类型的对象, 其下标都是 数字类型, 无法使用 .语法 只能用[]
    console.log(['mike', 'lucy', 'lily']);
​
    // 数组 和 对象的关系是?   数组是对象的一种
    // 就好像  人 和 男人的关系.  男人 是 人的一种
​
    var stu = {}
​
    var a = 'gege'
    // []: 里面是JS代码, a是变量, 其中的值是 'gege'
    stu[a] = '格格'
    // 问 :  格格这个值的 属性名是什么?
    // 选项1: a   选项2: gege.
​
    stu['a'] = '子轩'
    // 问: 子轩的属性名是?
    // 选项1: a     选项2: 'gege'
​
    var a = 'gg'
    stu.a = '家乐'
    // 问: 家乐的属性名是?  1
    // 选项1: a   选项2: gg
​
    // 语法
    // 对象.属性名  : 在点语法中, 就是个属性名, 不会变化
    // 对象[]:  方括号中是 JS 代码
    console.log(stu);
  </script>
</body>
​
</html>

el objeto es un tipo de referencia

Hay dos tipos de memoria:

Piense en la memoria como un diccionario/libro: dividido en dos partes: catálogo y página de detalles

为什么?: la tabla de contenido registra un título simple, que almacena el número de página de detalles y encuentra la página con contenido detallado a través del número de páginas

  • El contenido del directorio es pequeño y la velocidad de consulta es rápida.

Memoria de pila: equivalente a un directorio, almacena una pequeña cantidad de datos y tiene una velocidad de consulta rápida

Memoria heap: equivalente a la página de detalles, que almacena una gran cantidad de datos y tiene un número fijo de páginas

En JS, los tipos de datos básicos pertenecen a la categoría de pequeña cantidad de datos

  • número: 123, 12.3, 456

  • booleano:true false

  • nulo

  • indefinido

  • cadena: la cadena se 单个compone de varios caracteres

Tipos de datos básicos, al asignar,值传递

Tipo de objeto: Pertenece al tipo que almacena una gran cantidad de datos, y {}en él se puede almacenar cualquier cantidad de datos.

Almacenado en memoria en 堆内存, equivalente a en un libro 详情页, con un número de página

var objeto ={ 
 xx: xxx, 
 xx: xxx, 
 xxx:xxx 
}

El objeto es de 内存地址tipo referencia ( )

<!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>对象是引用类型</title>
</head>
​
<body>
  <!-- JS的数据类型有哪些? -->
  <!-- 基本数据类型: string boolean number null undefined + symbol bigInt -->
  <!-- 在 ES6 2015年 新增了 symbol(唯一,做属性名用)  bigInt(大整型) -->
  <!-- 引用/对象类型: object -->
​
  <script>
    // 猜猜 b 的值
    // 数字属于 number类型,  属于基础数据类型 -- 赋值时 属于 值传递
    var a = 5
    var b = a
    a = 10
    console.log(b) //5
​
    // 猜猜打印的结果
    var x = { num: 10 }
    var y = x
    x.num = 20
    console.log(y.num);
  </script>
</body>
​
</html>

copiar/clonar

<!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>对象的克隆</title>
</head>
​
<body>
  <!-- 克隆: clone  --复制,拷贝 -->
  <script>
    var x = { num: 10, ename: 'mike', age: 18 }
    // 克隆 x 对象: 分两步
    // 1. 创建1个空对象
    var y = {}
    // 2. 遍历x对象, 把其中的属性挨个存入空对象里
    // for..in.. 用于遍历对象
    for (var key in x) {
      // key: 是 x 对象中的属性
      console.log('key:', key);
      var value = x[key] // 对象 方括号取值
      // 把值存储在 y 这个空对象里
      y[key] = value
    }
​
    console.log('x:', x);
    console.log('y:', y);
​
    // 对比是否是同一个
    console.log('x == y:', x == y) //false: 不是同一个
​
    // 因为 x 和y 非同一个, 所以x的修改 不会影响 y
    x.age = 99
    console.log(y.age) // 18
  </script>
​
  <script>
    // 扩展小课堂:
    var a = { num: 10, count: 20 }
​
    var num = 'count'
​
    // 纯语法问题:  -- 成亮老师的JS基础有讲解!
    // 对象.属性名 : 点后面的就是属性名, 不是js代码
    // 对象[JS代码]
​
    console.log(a.num) //10
    // a[num] -> a['count']
    console.log(a[num]) //20
​
  </script>
</body>
​
</html>

el esto de la función

<!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>this关键词</title>
</head>
​
<body>
  <!-- this: 代表函数运行时所在的对象 -->
  <!-- 
    关键词 `我` : 代表说话时 的 人
    亮亮: 我今天要给 2204班上课
    娅楠: 我今天休息
    铭铭: 我今天被隔离, 在家直播
​
    这些 `我` 字 都代表什么?
   -->
​
  <script>
    // 全局中声明, 存储在window里
    function show() {
      // this: 这个
      console.log('我是:', this);
    }
​
    show() // 猜猜this
​
    var emp1 = { ename: '亮亮' }
    emp1.show = show // show函数存储到 emp1 里
    emp1.show()
​
    var emp2 = { ename: '娅楠', show: show }
    emp2.show()
​
    var a = 10
    var b = 20
    function c() { console.log(this) }
    // 属性名: 值(JS代码)
    // 简化语法: 属性名和值一样, 可以简化成一个 {b:b} -> {b}
    var obj = { num: 10, count: a, b, c: c }
    // 相当于
    obj.b = b
​
    obj.c() // 打印的this是什么
​
    console.log(obj)
​
    // 粗暴理解: 
    // 对象.方法()  : 方法中的this 就是前面的对象
    // 我.打亮亮() : 主语是   我
    // 涛哥.打亮亮() : 主语是 涛哥
    // 楠姐.打亮亮() : 主语是 楠姐
    // emp2.打亮亮() : this 就是 emp2
    // emp3.打亮亮() : this 就是 emp3
​
​
    var e1 = {
      name: '楠姐',
      打亮亮: function () {
        console.log(this, "在打亮亮");
      }
    }
    e1.打亮亮()
    // 函数中的this: 代表谁在使用
    var e2 = { name: '涛哥', 打亮亮: e1.打亮亮 }
    e2.打亮亮()
​
    // 面试的考点: 存储在window中的属性, 在使用时可以省略前缀
    var 打亮亮 = e1.打亮亮
    // window.打亮亮()
    打亮亮() //没有前缀 触发的方法, 都是window里的
  </script>
</body>
​
</html>

Cómo se crean los objetos

<!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>对象的创建方式</title>
</head>
​
<body>
  <!-- 语法糖: 作者提供的简化语法, 使用起来非常方便, 让人感觉幸福, 所以像吃糖一样甜蜜! -->
​
  <!-- 创建一个对象, 通常分两种方式 -->
  <!-- 1. 字面量: 一种语法糖,简化创建  -->
  <!-- 2. 构造方式 -->
  <script>
    // 数组的语法糖: 字面量
    var names = ['mike', 'lucy', 'lily']
    console.log(names);
​
    // 构造方式
    var names = new Array('tom', 'jerry', 'shirley')
    console.log(names);
​
    // 对象类型
    var emp = { name: '亚楠', age: 18, phone: '18332434344' }
    console.log(emp);
​
    // 构造方式
    var emp = new Object()
    emp.name = '凯凯'
    emp.age = 32
    emp['phone'] = '15534343444'
    console.log(emp);
​
    // 函数
    function aa(a, b) { console.log(a + b) }
​
    // 函数的构造写法:  前几个参数 是形参, 最后一个是函数体
    var bb = new Function('a', 'b', 'console.log(a + b)')
    console.log(bb);
    bb(20, 40)
​
    // 下节课主题: 我们自己做构造函数试一试
  </script>
</body>
​
</html>

el papel de este

 

 

<!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>this的作用 16:10</title>
  <!-- 在对象中复用函数,省内存 -->
</head>

<body>
  <script>
    // 矩形
    // 1个矩形, 长10  宽5   拥有方法area 来计算面积
    var r1 = {
      length: 10,
      width: 5,
      area: function () {
        // 长 x 宽
        return this.width * this.length
      }
    }

    console.log(r1);
    console.log(r1.area());

    // 创建r2对象, 长 20, 宽 30   area方法 算面积
    var r2 = {
      length: 20,
      width: 30,
      area: function () {
        return this.width * this.length
      }
    }
    console.log(r2.area());

    // 创建r3对象, 长 120, 宽 35   area方法 算面积
    var r3 = {
      length: 120,
      width: 35,
      area: function () {
        return this.width * this.length
      }
    }
    console.log(r3.area());

    // 思考1: r1 r2 r3 中都有area函数, 函数体一模一样
    // 他们是同一个函数吗??
    console.log(r1.area == r2.area) //不是同一个
    // area在不同的对象中声明的, 所以并非同一个函数

    // 思考2: 有必要吗?  同样功能的函数 声明3个 在不同对象里
    // 没必要, 浪费内存, 一个足够了

    // 怎么办?  提取area函数放在外面 共享即可
    function area() { return this.width * this.length }

    var r4 = {
      width: 100,
      length: 200,
      // area: area  语法糖: 属性名和变量名相同, 可以合写
      area
    }
    console.log(r4.area());

    // r5:  宽300, 长100  area方法
    var r5 = { width: 300, length: 100, area }
    console.log(r5.area()); // 函数()  ()是调用函数, 让函数运行

    // 思考1: r4的area 和 r5的area 是否相同?   是
    // 因为都引用的同一个函数
    console.log(r4.area == r5.area) // true

    // 思考2: 为什么函数书写在外部, 引入到不同的对象里, 就能为所在的对象服务??
    // 因为 灵活的 this 关键词: 函数在哪个对象里执行, 就代表哪个对象
    // this是特别好用的特性: 实现节省内存, 在不同对象里复用函数
  </script>
</body>

</html>

Constructor

<!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>构造函数</title>
</head>

<body>
  <script>
    function area() { return this.width * this.length }
    // 手动方式: 创建一个对象 -- 麻烦,容易写错
    var r1 = { width: 10, length: 20, area }
    console.log(r1.area());

    // 利用函数快速创建对象

    // 相当于工厂/流水行:  提供原材料 即 30, 50
    // 内部就会加工成 矩形对象并 返回
    function Rectangle(a, b) {
      // 函数的形参名随便起
      var obj = {}

      obj.width = a
      obj.length = b
      obj.area = area

      return obj
    }

    var r2 = Rectangle(30, 50)
    console.log(r2);
    console.log(r2.area());

    // 自动化思想: 利用函数 把步骤都固定写好
    // 每次使用时, 提供参数即可, 函数自然会完成剩余的所有操作
    // 这种用来生产 对象的函数 -- 称为 构造(对象的)函数
    var r3 = Rectangle(10, 40)
    var r4 = Rectangle(440, 44)

  </script>
</body>

</html>

Dos cosas sobre el constructor.

  • esta palabra clave: extraiga los métodos comunes en el objeto al almacenamiento externo

  • Constructor: la idea de la automatización, encapsula los pasos para convertir objetos en funciones y llama a las funciones para completar automáticamente la creación de objetos

Ejercicio de constructor

<!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>练习</title>
</head>

<body>
  <script>
    // 员工对象
    // salary: 薪资
    var e1 = {
      ename: '楠姐',
      age: 18,
      salary: 22000,
      salary_year: function () {
        return this.salary * 12
      }
    }
    console.log(e1);
    console.log(e1.salary_year());

    // 制作一个生产 员工对象的 构造函数, 用来自动生成对象
    // 练习: 模仿上节课的, 实现这个 构造函数

    function salary_year() {
      return this.salary * 12
    }

    // 变量名: 见名知意
    function Employee(ename, age, salary) {
      // 1.制作一个空对象
      var obj = {}
      // 2.把传入的参数存储在对象里
      obj.ename = ename
      obj.age = age
      obj.salary = salary

      obj.salary_year = salary_year

      // 3.返回制作完毕的对象
      return obj
    }

    // e2   凯凯  32  15000
    var e2 = Employee('凯凯', 32, 15000)
    console.log(e2.salary_year());
    // e3   涛哥  40  30000
    var e3 = Employee('涛哥', 40, 30000)
    console.log(e3.salary_year());
  </script>

  <script>
    // 立方体: 
    var c1 = {
      length: 100, //长
      width: 40, //宽
      height: 10, //高
      //体积: 长x宽x高 
      volume: function () {
        return this.width * this.length * this.height
      },
      // 周长: (长+宽+高)*4
      perimeter: function () {
        return (this.width + this.height + this.length) * 4
      }
    }

    console.log(c1);
    console.log(c1.volume());
    console.log(c1.perimeter());

    // 练习: 制作 Cube 函数, 用来生产 立方体 对象
    function volume() {
      return this.width * this.length * this.height
    }

    function perimeter() {
      return (this.width + this.height + this.length) * 4
    }

    function Cube(length, width, height) {
      // 1. 空对象
      var obj = {}
      // 2. 加入数据
      obj.length = length
      obj.width = width
      obj.height = height
      // 3. 添加函数 -- 省内存, 把函数在外部声明
      obj.volume = volume
      obj.perimeter = perimeter
      // 4. 返回
      return obj
    }

    // 使用时:
    var c2 = Cube(10, 20, 30) // 顺序是 长 宽 高
    console.log(c2.volume());
    console.log(c2.perimeter());

  </script>
</body>

</html>

Resumen del contenido de hoy.

  • argumentos de función

    • Una variable oculta que viene con la función.

    • Guarda todos los parámetros reales recibidos por la función

    • El tipo es un objeto, que parece una matriz: array-like/pseudo-array

      • Varios métodos que no pueden usar arreglos

  • Sobrecarga de funciones: realice diferentes operaciones lógicas juzgando el número/tipo de parámetros de la función

    • Función: haga que una función sea más poderosa y pueda completar diferentes tareas

    • Enfoque: use if para juzgar, con el atributo arguments

  • Sintaxis de acceso: Sintaxis de puntos Sintaxis de corchetes --- Vaya a la parte brillante para revisar

  • el objeto es un tipo de referencia

    • concepto de pila

    • Pila: almacene una pequeña cantidad de datos, la velocidad de consulta es rápida: un catálogo similar a los libros

    • Montón: almacena una gran cantidad de datos, similar a la página de detalles de un libro

    • El tipo de objeto se almacena en la pila como su dirección de memoria, por lo que se llama: transferencia de dirección

  • Clonar objeto:

    • Cree un nuevo objeto vacío, recorra el objeto de destino y asigne las propiedades al objeto vacío una por una

  • esta palabra clave:函数是哪个对象调用的, 其中的this就是哪个对象

    • 楠姐.打亮亮(): Esta en Liangliang es la hermana Nan.

  • porque hay esto

    • Extraiga funciones comunes en múltiples objetos al almacenamiento externo.

    • Utilice el cambio flexible de this, qué objeto servirá qué objeto se ejecuta

  • constructor de objetos

    • Constructor: similar a una fábrica, que proporciona materias primas, producirá productos de acuerdo con pasos fijos

    • Pasar parámetros a la función para generar un objeto con una estructura fija

Operación

Ejercicio de sobrecarga de funciones

Haz una función max que pueda encontrar el valor máximo

máximo (11,22,33,44)

máx. (43,54,65,656,12,5)

máx([32,4,546,57])

máx([32,4,546,57, 5, 67,7])

pista:

  • Hay dos formas de pasar parámetros: pasar una pila de números o pasar un tipo de matriz

  • La idea de encontrar el valor máximo: primero declare una variable a igual al primer elemento de la matriz y luego recorra la matriz a partir del número de serie 1. Si el nuevo valor es mayor que a, simplemente reemplace el valor en un

Ejercicio de constructor

Hacer un constructor que produzca el objeto estudiante.

El objeto de estudiante se ve así:

var s1 = { 
 sname: 'Kaikai', 
 age: 19, 
 phone:'18844341111', 
 // devuelve si es un adulto 
 isAdult: function(){ 
     return this.age >= 18 
 } 
}

Cómo se ve el constructor fabricado cuando se usa

var s2 = Student('亚楠', 18, '198382932323') 
console.log(s2.isAdult()) 

var s3 = Student('梦瑶', 15, '158779787874') 
console.log(s3.isAdult( ) ))

JSCORE03

revisar

  • impulso de declaración

    • Características únicas de JS: no es bueno

    • Después de escribir el código JS, 隐式la estructura del código se ajustará cuando realmente se ejecute, y las operaciones de declaración se promoverán a la parte superior del ámbito de almacenamiento y luego se ejecutarán.

      Puntos de prueba de la entrevista: el funcionamiento del código JS es diferente de lo que ves con tus ojos

    • Palabras clave de declaración:var/function/class/let/const

  • Alcance: Es esencialmente un 对象tipo, pero se llama alcance porque tiene un rol especial

    • Global: objeto de ventana

    • Local: la función 运行时generará temporalmente un objeto, que contiene las variables declaradas en la función

    • let/const/classGuión: declarado en el guión usando

    • Nivel de bloque: declarado {}enlet/const/class

  • Cadena de alcance: el entorno de escritura del código --词法环境

    • Cuando se utiliza una variable en una función, primero se busca en su propio ámbito, si no, se busca en el superior.

  • Cierre

    • Cuando se declara la función, llevará todos los ámbitos en los que se encuentra y la almacenará en scopesel atributo

      • estático: declaraciones de funciones: los ámbitos se almacenan en ámbitos

      • Dinámico: llamada de función (): lea el valor en el alcance de los alcances para usar

    • Entre ellos: el alcance de la función almacenado en los alcances, llamado cierre Cierre

    • Función: antes de ES6, declarar variables locales para evitar la contaminación global

  • argumentos

    • Un atributo en la función 隐式, que almacena todos los parámetros reales recibidos cuando se usa la función

  • sobrecarga de funciones

    • Una técnica que ejecuta una lógica diferente juzgando el número o tipo de parámetros en el cuerpo de la función.

    • Rol: Deje que una función haga múltiples cosas, más poderosa

    • Método: usar ifjuntosarguments

  • tipo de referencia

    • Hay 8 tipos de datos

      • Tipo básico ( 体积小): número de cadena booleano nulo símbolo indefinido bigInt

      • Tipo de referencia (el volumen no es fijo, grande): objeto

    • Parte de la memoria: memoria de pila de memoria montón

      • Memoria de pila: es equivalente al catálogo de libros, adecuado para almacenar datos pequeños y la velocidad de consulta es rápida

      • Memoria heap: equivalente a la página de detalles de un libro, adecuada para almacenar grandes datos, con direcciones de memoria

    • El tipo de objeto se almacena en la memoria del montón como datos de gran tamaño; la variable guarda el tipo de objeto y, de hecho, almacena la dirección del tipo de objeto: tipo de transferencia de dirección/referencia (dirección de memoria)

  • este

    • Una palabra clave en la función, que representa el objeto en el que se ejecuta la función

      • 楠姐.打亮亮(): 打亮亮esto en el método es楠姐

    • Función: Deje que la misma función se use en diferentes objetos, debido a esta palabra clave, se adaptará automáticamente al objeto donde se encuentra para ahorrar memoria.

  • Constructor:构造 固定结构的对象 的函数

    • Encapsule el proceso de fabricación de algunos objetos en una función. Después de llamar a la función, el objeto se puede generar automáticamente

Operación

<!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>作业</title>
</head>
​
<body>
  <script>
    // max函数, 求最大值
    function max() {
      // arguments: 存储了所有的参数
      // console.log(arguments);
      // 思维: 先看第一个, 暂定为最大
      // 然后再看下一个, 如果下一个更大, 则 替换掉之前 暂定的最大
      // 写程序 就是把 你的思维 转换成 代码 告诉计算机如何操作
      if (Array.isArray(arguments[0])) {
        //读取参数数组
        var arr = arguments[0]
        var m = arr[0]
​
        for (var i = 1; i < arr.length; i++) {
          if (arr[i] > m) m = arr[i]
        }
        console.log(m);
​
      } else {
        var m = arguments[0]
        for (var i = 1; i < arguments.length; i++) {
          // if判断的 {}中只有一行, 可以省略{}
          if (arguments[i] > m) m = arguments[i]
        }
        console.log('最大数:', m);
      }
    }
​
    max(12, 43, 4565, 675)
    max(12, 43, 4565, 675, 1111, 23, 43)
​
    max([43, 5, 65, 7, 78])
  </script>
​
  <script>
    // 构造学生对象
    // 把对象中使用的函数 在外部声明: 共享 省内存
​
    // 思考: 共享的函数 如果存储在 全局区, 会造成全局变量污染
    // 办法: 作者为函数提供了一个专有的属性 prototype(原型), 专门存储共享的方法
    function isAdult() {
      return this.age >= 18
    }
​
    function Student(sname, age, phone) {
      var obj = {}
      obj.sname = sname
      obj.age = age
      obj.phone = phone
      // 错误: function关键词会声明新的函数. 每次运行都会声明一个新的. 浪费内存
      // obj.isAdult = function () { }
      obj.isAdult = isAdult
​
      return obj
    }
​
    var s1 = Student('凯凯', 19, '18844341111')
    console.log(s1);
    console.log(s1.isAdult());
  </script>
</body>
​
</html>

JSCORE04

revisar

  • impulso de declaración

    • Cuando el código JS está presente 真正运行, el orden del código debe 隐式ajustarse y el código de la operación de declaración se promueve a la parte superior del ámbito de ejecución.

    • El orden real del código escrito y el código en ejecución es diferente.面试考点

    • Palabras clave de declaración:var/function/let/const/class

  • alcance

    • ¿Qué es el alcance?本质就是一个对象类型, 只是因为有特殊作用, 所以称为 作用域

    • 4 alcances:

      • Ámbito global: en 浏览器este 宿主环境caso, el objeto ventana.

      • Ámbito local: 运行时el tipo de objeto creado temporalmente por la función, que almacena las variables declaradas en la función

        • Al comienzo de la ejecución de la función: 创建; Al final de la ejecución de la función:销毁

      • Alcance del script: ES6 en adelante

        • Uso let/constdeclarado en el script, almacenado en el área del script

      • Alcance del bloque: ES6 en adelante

        • uso {}con let/constuso

  • Cierre: una habilidad que viene con la función: cuando se declara la función, guardará su ubicación 词法作用域en scopesla propiedad

    • 词法作用域: Todos los ámbitos de la capa exterior donde se encuentra la función

    • El cierre es un nombre especial cuando 函数作用域se guarda en propiedadesscopes

      Cuando se activa una función, formará un ámbito de función, en el que hay una variable x

      La función b se declara en la función a, y se usa la variable x de la función a

      El alcance de la función a se almacenará en el atributo de alcance de la función b, que se denomina cierre

      function a(){
          var x = 10
          
          function b(){
              console.log(x)
          }
      }
      ​
      a()
  • sobrecarga de funciones

    • argumentos: una variable que viene con la función, que almacena todos los parámetros recibidos por la función

      • Escenario de uso: cuando el número de parámetros de una función 不固定, use

    • Aplicación: sobrecarga de funciones

      • En el cuerpo de la función, juzgue 个数si los parámetros 类型son diferentes y ejecute una lógica de código diferente

      • Deja que 1 función haga múltiples operaciones

  • objeto

    • 8 tipos de datos

      • Conceptos básicos: número de cadena booleano nulo indefinido + símbolo y bigInt

      • objeto de tipo de objeto

    • Tipo de referencia:

      • Memoria heap: equivalente a la página de detalles de un libro, almacena muchas cosas, con内存地址

      • Memoria de pila: equivalente al catálogo de libros, con mayor velocidad de consulta y menor contenido de almacenamiento

    • Tipo de objeto, almacenado en la memoria del montón

    • Las variables se almacenan en la memoria de pila y sus valores son de tipo objeto地址

    • Referenciado 对象类型的地址, asignación entre objetos ---地址传递

  • esta palabra clave

    • La palabra clave this de la función, que representa 运行时la ubicación de la función对象

    • efecto:省内存

    • Cómo funciona: una función se puede reutilizar en varios objetos:复用

  • Constructor

    • La función utilizada para crear un tipo de objeto es el constructor.

    • Escritura ordinaria:

      function Demo(x, y){
          var obj = {} //1. 先创建空对象
          
          // 把参数存储在对象里
          obj.x = x
          obj.y = y
          
          // 原型链 __proto__ 指向 函数的原型
          obj.__proto__ = Demo.prototype
          
          return obj //2. 返回对象
      }
      ​
      // 对象共享的方法, 存储在原型中
      Demo.prototype.area = function(){}
      Demo.prototype.xxyy = function(){}
       
    • newOperadores: 构造函数palabras clave proporcionadas por el autor para simplificar, 3líneas de código implícitamente completas

      function Demo(x, y){
          var this = {}
          
          this.x = x
          this.y = y
          
          this.__proto__ = Demo.prototype
          
          return this
      }
      ​
      // 配合new使用
      function Demo(x, y){
          this.x = x
          this.y = y
      }
      ​
      var d1 = new Demo(10, 20)
  • Modo estricto

    • Versión ES5 producida en 2009

    • En modo estricto, si el código escrito tiene 风险 un fondo, se informará un error

    • Método de apertura: escriba en la parte superior del código JS use strict

    • Las variables deben declararse primero y luego usarse: para evitar la contaminación de variables globales causada por nombres de variables escritos incorrectamente

    • El esto del constructor, desencadenando directamente esto no está definido, para evitar la contaminación global.

    • Evitar fallas silenciosas: lo que antes fallaba sin un error ahora informa un error

  • Configuración precisa de las propiedades de los objetos

    • Object.defineProperty(对象, 属性名, 配置项)

    • Elementos de configuración:

      • configurable: si se puede reconfigurar, si se puede eliminar la propiedad

      • enumerable: Traversable -- si for..in puede atravesar a

      • writable: modificable -- si el valor se puede cambiar

      • valor: valor por defecto

      • obtener: Propiedad calculada -- el valor es un tipo de función, pero puede activarse sin usar () -- simple

colocar

<!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>精确属性配置 - 赋值监听</title>
</head>
​
<body>
  <script>
    var emp = {
      ename: '亚楠',
      _age: null, // 用于存储 检查站 age 检查出来的值
    }
​
    // 为 age 属性, 添加检查站: 监听器 set(设置)
    Object.defineProperty(emp, 'age', {
      // 计算属性get: 特点 值是函数,但使用时不用()
      // get: function () { },
      get() {
        // emp._age
        return this._age;
      },
      // set: 检查站属性, 值是函数
      // set: function (value) { }
      // 语法糖: 省略 function 
      // 参数value: 就是设置给 age 属性的值, 
      // 例如 emp.age = 200, 就是这个200
      set(value) {
        console.log('age赋值为:', value);
        // 检查标准: age 1~100
        if (value >= 1 && value <= 100) {
          // 如果正确, 则赋值给 _age
          // age是监听器/检查站, 只负责检查, 不负责存值
          // _age 是配合 age检查站使用的属性, 用来存储值
          this._age = value
        } else {
          // 抛出错误, 提醒用户
          throw Error('age合法范围1~100, 您的赋值:' + value)
        }
      }
    })
​
​
    // 修改age 年龄
    // 问题: 娅楠的年龄不可能是200, 明显的错误
    // 期望: 监听这个赋值操作, 如果值明显不对, 则报错, 给出提示
    // emp.age = 200
​
    // 用户看到: 把100 存储到 age 属性里
    // 本质age是检查站不存值, 但是用户不知道, 用户只看表面
    emp.age = 100
    // 外观上: 就应该从 age 读取值
    console.log(emp.age);
    // emp.age: 实际上age是个函数,但是因为是get计算属性, 不要()
    // 从外观上看起来: 好像是在读属性
​
    // 楠姐.打亮亮() : this就是楠姐
    // emp.age() : this就是 emp
​
    console.log(emp);
    // 读取年龄: 从_age读取完全没问题
    // 但是: 从用户角度来看
    console.log(emp._age);
  </script>
</body>
​
</html>

Bucle infinito

Eventualmente se excede el límite máximo de memoria, fallando

Dado que ageel atributo se transforma en 检查站/监听器, 不再tiene 存储值el efecto de

Solución: 再制作一个属性用来存储 合法的值solo

  • Convención de nomenclatura: es habitual (no obligatorio) almacenar el valor de la verificación de edad exitosa. El nombre del atributo _agees más apropiado. Agregue uno _, y cuando lea el código 一目了然, sabrá que el contenido del punto de control _ageestá almacenadoage

práctica

<!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>练习</title>
</head>
​
<body>
  <script>
    var emp = {
      ename: "凯哥",
      // 配合 salary 检查站, 创造一个仓库 用来存储对应的值
      // 写法上: 最好是 _开头, 名字一目了然
      _salary: 20000
    }
​
    // 把 salary 属性修改成 检查站/监听器, 不再负责存储数据
    Object.defineProperty(emp, 'salary', {
      // 让 salary 使用时, 不用() 也能触发
      get() { return this._salary },
      set(value) {
        if (value >= 5000 && value <= 30000) {
          // salary属性本身已经变身为 检查站 - 无法存数据
          // 所以搭配一个 仓库用来存数据
          this._salary = value
        } else {
          throw Error('月收入不合理:' + value)
        }
      }
    })
​
    // 希望报错, 合理的薪资是 5000 ~ 30000
    // emp.salary = 100000
​
    // 用户角度: 眼看着存储在 salary 属性的
    // 但是却要从 _salary中读取 : 另用户感觉到迷惑
    emp.salary = 12000
    // 读取时: 增加一个 salary的 get计算属性, 能够返回 _salary的值
    console.log(emp.salary);
    console.log(emp);
  </script>
</body>
​
</html>
<!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>练习</title>
</head>
​
<body>
  <script>
    var stu = {
      sname: "亮亮",
      _sid: 10001 //学号
    }
​
    // 把 sid 属性, 转变成 检查站, 不再能够存储值
    Object.defineProperty(stu, 'sid', {
      get() { return this._sid },
      set(value) {
        if (value >= 1 && value <= 100000) {
          this._sid = value
        } else {
          throw Error('学号范围错误:' + value)
        }
      }
    })
​
    // 学号范围是 1-100000
    // stu.sid = 200000 //要求弹出报错: 提示学号范围不对
​
    // 注释掉 19行代码
    stu.sid = 2000 //能够正常存储
    console.log(stu.sid) // 能够打印出2000  -- 计算属性
    console.log(stu);
​
  </script>
</body>
​
</html>

llamar

<!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>call</title>
</head>
​
<body>
  <script>
    // 函数的call方法: 用于指定函数使用时的this关键词指向
​
    // 函数的this: 指向运行时所在的对象
    // 例如  楠姐.打亮亮() -- this就是楠姐
​
    // 函数分两种状态:声明时 和 运行时
​
    // 声明:   问: this是什么?  不可能知道--运行时决定
    // 举例: 马路边停了一辆车, 问: 司机是谁? -- 开起来才知道
    function 打亮亮() {
      console.log(this.uname, '使劲打亮亮');
    }
​
    var emp = { uname: "娅楠" }
    // 把 打亮亮 这个函数, 存储到 emp 里
    emp.hit = 打亮亮
    emp.hit()
​
    var emp1 = { uname: '凯哥' }
    emp1.hit = 打亮亮
    emp1.hit()
    delete emp1.hit //删除 hit 属性, 毁灭证据
​
    // 又把 公用的锤子
    // 1. 把锤子拿到手里  2.用锤子打亮亮  3.把锤子扔掉
    console.log(emp1);
​
    // 打亮亮方法在使用时分两步: 
    // 1. 先把此方法存储到 对象里
    // 2. 再通过对象来调用
    // 3. 删除打亮亮方法, 因为是临时使用
​
    // 官方为了用户使用方便, 封装了一个call方法, 能够自动把函数放在对象里, 进行调用, 随后进行删除
    // 函数的构造方式:  new Function()
    // 所以 函数.__proto__ == Function.prototype
    console.dir(打亮亮);
    // 函数具有一个call
    // 函数.call(obj):  隐式 把函数存储在obj里, 然后通过obj调用
    打亮亮.call(emp1)
​
    var emp2 = { uname: '涛涛' }
    // 两种做法:
    // 做法1: 手动模式
    // - 把 打亮亮 存储在 emp2 中, 属性名叫 hit, 可以随便起名
    emp2.x = 打亮亮
    // - 调用 hit 方法
    emp2.x()  // 打亮亮的 this 就是 emp2
    // - 删除 hit 属性, 毁灭证据
    delete emp2.x
    console.log(emp2);
​
    // 做法2: 系统提供的快速隐式完成以上操作 -- call
    打亮亮.call(emp2)
  </script>
</body>
​
</html>

llamar con parametros

<!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>call携带参数</title>
</head>
​
<body>
  <script>
    function 打亮亮(time) {
      // time: 次数
      console.log(this.uname, '打亮亮', time, '次');
    }
​
    var emp1 = { uname: "楠姐" }
    // 1. 把 打亮亮 放在 emp1 里
    emp1.xx = 打亮亮
    // 2. 调用 emp1 的打亮亮
    emp1.xx(5)
    // 3. 删除掉 emp1 中存储的 打亮亮
    delete emp1.xx
​
    // 使用系统提供的 call 方式
    // 函数.call(对象, 参数): 自动隐式完成 - 把函数放对象里,调用后,删除
    // call() 从参数2开始, 就是传递给函数本身的参数
    打亮亮.call(emp1, 10) // emp1.打亮亮(10)
​
    // 范式:  fn.call(A, B) ->实际执行 -> A.fn(B)
​
    // 计算 n个月 支付的薪资
    function pay(n) {
      console.log(this.salary * n);
    }
​
    var emp2 = { ename: "凯凯", salary: 14000 }
    var emp3 = { ename: "涛涛", salary: 24000 }
​
    // 计算 emp2 10个月的薪资
    pay.call(emp2, 10)
    // 计算 emp3 4个月的薪资
    pay.call(emp3, 4)
​
    function show() {
      console.log(arguments);
      // 向 arguments 中, 新增 55 66 77 3个值
      // arguments: 类数组, 长得像数组 但 原型不是, 没有数组的方法
      // 数组: push
​
      // 把数组的 push 方法临时放到 arguments 中使用一次
      // arguments.push(55, 66, 77)
      Array.prototype.push.call(arguments, 55, 66, 77)
      // 数组的push方法: 构造函数Array的原型prototype里
    }
​
    show(11, 22, 33, 44)
  </script>
</body>
​
</html>

aplicar

<!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>apply</title>
</head>

<body>
  <script>
    // apply: 与 call 作用十分相似
    // 都是临时把函数放在对象里执行
    function pay(n, off) {
      // off: 折扣
      console.log(this.salary * n * off);
    }

    var emp = { ename: "凯凯", salary: 14000 }
    // 用call 算出10个月工资: 把pay临时放到 emp 中执行
    pay.call(emp, 10, 0.7)
    // apply: 临时把函数放在对象里执行, 差异: 参数放数组中传递
    pay.apply(emp, [10, 0.7])

    // apply的用途: 把 1个1个 传递的参数, 改为用数组传递

    // 求最大值: Math.max()
    var m = Math.max(12, 43, 2154, 657, 67, 21)
    console.log(m);

    // 找出数组中的最大值
    var nums = [123, 345, 546, 657, 67]
    // max: 只能接收 1个1个传递的参数
    // apply: 把数组作为函数的参数, 数组->1个1个传递的
    // Math.max.apply(A, B) -> A.Math.max(B)
    // Math.max 不需要存储在任何对象中, 独立就能运行, 所以参数1 随便写, 没有任何影响
    var m = Math.max.apply(0, nums)

    // ES6之前, 只能用 apply 来转换数组 为参数
    // ES6之后, 有扩展符  ... 更方便, 后续讲解
    console.log(m);
  </script>
</body>

</html>

unir

<!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>bind</title>
</head>

<body>
  <script>
    // bind: 与call相似
    // call: 临时 把函数放在对象中, 立即执行
    // bind: 永久 把函数放在对象中, 不会立即执行, 返回处理后的函数

    function pay(n) {
      console.log(this.salary * n);
    }

    var emp = { ename: "凯凯", salary: 14000 }
    // 用call实现 10个月工资
    pay.call(emp, 10)

    // bind(): 不会触发pay函数, 而是返回一个值
    // 返回值是一个函数, 其中的 BoundThis 属性存储了this指向
    // 其中的 BoundArgs : 存储了相关参数

    // 打比方: 一把手枪
    // call: 填充弹药 -> 立刻激发
    // bind: 填充弹药 -> 返回这把带有弹药的手枪
    var pay_b = pay.bind(emp, 10)
    console.dir(pay_b);

    // 在后续, 用()来触发
    pay_b()

    // 实际工作用途:
    // 1. 配合定时器使用: 延时执行
    // 2. 在 React 框架中常用: 2个月后的 5阶段会用到
  </script>
</body>

</html>

llamada de función, enlazar, aplicar

面试Preguntas de examen de uso frecuente, 造火箭de uso frecuente, 日常de uso poco frecuente

  • llamada: Modificar temporalmente el este punto de la función, transferencia 立刻触发de parámetros1个1个

  • aplicar: Modificar temporalmente el este punto de la función, transferencia 立刻触发de parámetros数组

  • bind: vincula parámetros y funciones, y devuelve esta función. 不会触发, se puede activar en cualquier momento posterior

función de flecha

<!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>箭头函数</title>
</head>

<body>
  <script>
    // ES6 2015年提供的 新语法 - 箭头函数
    // 优点1: 丰富的语法糖 带来简化写法
    // 作用: 带来了 新的 this 指向方式
    // 注意: 不能做 构造函数

    // function (){}
    // 从格式上: 简化了 匿名函数自调用的写法
    (function () { })();

    (() => { })()

    // 语法糖1: 箭头函数只有一个参数, () 可以省略
    var a = (name) => {
      console.log(name, '666');
    }

    // 简化
    var a = name => {
      console.log(name, '666');
    }

    a('凯凯')
    a('楠楠')

    // 语法糖2: 函数体只有1行代码时, 可以省略 { return ... }
    var a = (n) => { return 14000 * n }

    var a = n => 14000 * n

    console.log(a(12));

    // 练习: 尝试省略
    var b = (x, y) => { return x + y }
    var b = (x, y) => x + y

    var c = (y) => { return 12 * y }
    var c = y => 12 * y

    var d = () => { return 666 * 888 }
    var d = () => 666 * 888

    // 坑:
    var e = (name, age) => { return { name: name, age: age } }
    // 返回值是对象类型, 带有{}, 会被识别为 函数体的{}
    // 用()包围, 才会识别为 普通的对象类型
    var e = (name, age) => ({ name, age })

    console.log(e('马鑫鑫', 23));
  </script>
</body>

</html>
<!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>箭头函数的this</title>
</head>

<body>
  <script>
    // function: this指向运行时所在的对象
    // 箭头函数: this指向声明时所在的作用域的this

    // 类似: 涛哥买个锤子, 打亮亮
    // function:  楠姐.打亮亮()   锤子的使用者是楠姐 this
    // 箭头函数:  楠姐.打亮亮()    锤子的购买者 - 涛哥: 永远不变

    // 另一个例子:
    // 家乐的妈妈: - 相当于 箭头函数, 家乐不管在哪里都不会变, 出生的时候就锁死

    // 家乐的女朋友: 今天是 热巴  明天是杨幂 后天 -马尔扎哈  - function. 会变化

    console.log(this) // 全局中打印this, 就是window

    // 这个箭头函数 在哪个对象中声明的: 全局中 window
    var 三打亮亮 = () => {
      console.log(this, '三打亮亮');
    }

    function 打亮亮() {
      console.log(this, '在打亮亮');
    }

    var emp = { uname: "楠姐" }

    emp.x = 打亮亮
    emp.x()

    // 把箭头函数放在 emp 里
    emp.y = 三打亮亮
    emp.y()
  </script>
</body>

</html>

cada

<!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>every</title>
</head>

<body>
  <script>
    // 数组的高阶函数
    // 高阶函数: 如果一个函数中, 使用了另一个函数, 就叫高阶函数
    // 类似: 家乐 有孩子了, 家乐称为: 父亲
    // 例如: 数组有一个 sort 排序, 例如 sort( (a,b)=> a-b )

    // 以后: 从服务器上查询出数据, 往往都是数组类型, 在JS中提供了大量的处理 数组类型的 函数

    // every: 每一个. 用于遍历数组, 检查每一个元素是否符合条件
    var nums = [12, 22, 14, 12, 4]
    // 检查: 数组的每个元素是否都是 偶数

    // every的参数: 要求是函数类型, 函数固定接收3个参数
    // every会遍历 nums 中的每一个元素, 传递给函数
    var a = nums.every((value, index, array) => {
      // 箭头函数的形参名: 随便起
      // 顺序固定: 值, 序号, 数组本身
      console.log('value:', value);
      console.log('index:', index);
      console.log('array:', array);
      console.log('------------------');
      return value % 2 == 0
    })

    console.log('a:', a);
    console.log(a ? '都是偶数' : '非都是偶数');

    // 练习
    var nums = [12, 3, 5, 65, -3]

    // 判断是否都是正数 > 0
    var a = nums.every((value, index, array) => {
      return value > 0
    })

    // 没用到的参数, 可以不用声明
    var a = nums.every((value) => {
      return value > 0
    })

    // 箭头函数: 单参数省略()   函数体只有1行 {return }
    var a = nums.every(value => value > 0)
    // 参数名随便起, 但是原则: 见名知意
    var a = nums.every(x => x > 0)


    console.log(a);
    console.log(a ? '都是正数' : '非都是正数');

    var nums = [12, 3, 45, 5465, 765]
    // 判断是否都大于10
    var a = nums.every(v => v > 10)
    console.log(a ? '都大于10' : "非都大于10");

    // 实际案例:
    var products = [
      { pname: 'iPhone', price: 9000, count: 10 },
      { pname: 'v80x', price: 6000, count: 1 },
      { pname: 'findx5', price: 5500, count: 5 },
      { pname: 'magic 5', price: 6000, count: 6 },
    ]
    // 需求: 判断商品的单价是否都高于 5000
    // 数组的每个元素是对象类型
    var a = products.every(value => value.price > 5000)
    console.log(a ? '都大于5000' : '非都大于5000');
    // 判断: 数量是否都少于3个的
    var a = products.every(value => value.count < 3)
    console.log(a ? '都少于3个' : '非都少于3个');
  </script>
</body>

</html>

alguno

<!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>some</title>
</head>

<body>
  <script>
    // some: 有些, 判断数组中至少有一个满足条件的元素
    // 类似于 逻辑或 ||  -- 有一个真 最终结果是真
    var nums = [11, 43, 5, 677, 1]
    // 判断: 是否有偶数
    // some的所有参数 都和 every 一样
    var a = nums.some((value, index, array) => {
      return value % 2 == 0
    })

    // 简化后:
    var a = nums.some(value => value % 2 == 0)

    console.log(a ? '有偶数' : '没有偶数');

    var emps = [
      { ename: "凯凯", age: 32 },
      { ename: "亮亮", age: 37 },
      { ename: "亚楠", age: 18 },
    ]
    // 查看是否 有 小于20岁的人
    var a = emps.some(value => value.age < 20)

    console.log(a ? '有' : '没有');
  </script>
</body>

</html>

filtrar

<!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>filter</title>
</head>

<body>
  <script>
    // filter: 过滤器, 把数组中满足条件的元素 组成新的数组返回
    var nums = [12, 3, 43, 65, 12, 546, 7, 6]
    // 找出所有的偶数

    var a = nums.filter((value, index, array) => {
      // 真: 过滤出来   假: 阻拦
      return value % 2 == 0
    })

    // 简化:
    var a = nums.filter(value => value % 2 == 0)

    console.log(a);

    var emps = [
      { ename: "凯凯", salary: 14000 },
      { ename: "亮亮", salary: 34000 },
      { ename: "楠姐", salary: 20000 },
      { ename: "涛涛", salary: 24000 },
    ]
    // 找出所有 薪资大于20000的人
    var a = emps.filter(value => value.salary > 20000)
    console.log(a);
  </script>
</body>

</html>

mapa

<!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>map</title>
</head>

<body>
  <script>
    //map: 映射 - 把数组中的每个元素 处理后, 返回值组成新的数组
    var nums = [12, 34, 5, 65, 23, 43, 6]

    // 希望: 每个数字都 x2
    var a = nums.map((value, index, array) => {
      return value * 2
    })

    // 简化:
    var a = nums.map(value => value * 2)

    console.log(a);

    // 实际用途: 把数据转换成 HTML 字符串, 最常用
    var girls = ['迪丽热巴', '古力娜扎', '马尔扎哈', '努尔哈赤']
    // 把每个元素, 放在按钮标签里  <button>xx</button>
    var a = girls.map(value => {
      // ES6提供了 模板字符串, 转为拼接HTML而生
      // 符号 `` 反引号, 特殊标识 ${} 代表JS代码
      return `<button>${value}</button>`
    })

    console.log(a);

    var webs = [
      { name: "百度一下", href: "http://www.baidu.com" },
      { name: "Tmooc", href: "http://www.tmooc.cn" },
      { name: "斗鱼", href: "http://www.douyu.com" },
      { name: "哔哩哔哩", href: "http://www.bilibili.com" },
    ]

    // 要求: 映射成 超链接 字符串组成的数组
    // 例如  <a href="http://www.baidu.com">百度一下</a>
    var a = webs.map(value => `<a href="${value.href}">${value.name}</a>`)

    console.log(a);
  </script>
</body>

</html>

resumen de contenido

  • configuración del conjunto de atributos

    • Convertir una propiedad en 监听器/检测站: implementar detección de asignación

    • Empareje con otro atributo para almacenar el valor real

    • Obteniendo propiedades calculadas, engañando a los usuarios, proporcionando una forma amigable de leer y escribir valores

  • 3 métodos de activación de la función

    • llamada: activa la función mientras especifica el objeto de esta

    • enlazar: no active la función, vincule el parámetro a esto y actívelo en cualquier momento posterior

    • aplicar: activa la función mientras especifica el objeto de este, cuyo parámetro es una matriz

  • función de flecha

    • Azúcar sintáctico: (name)=>{ return name + 11 }omitir ()y{}

      name => name + 11

    • this apunta a: the this del ámbito donde fue declarado

  • matriz de funciones de orden superior

    • cada: cada elemento satisface la condición, lógica similar y && debe ser verdadero

    • algunos: al menos un elemento satisface la condición, similar a la lógica o || solo uno verdadero

    • filtrar: filtrar, filtrar los elementos que cumplen las condiciones y formar una nueva matriz

    • map: mapeo, el valor devuelto después de que cada elemento se procesa para formar una nueva matriz ( 很常用)

Operación

Tarea 1:

var p = { pname:"iPhone", count: 5, price: 9999}

p.count = -10 //报错: 范围在 0 - 100000
p.count = 40 //正常赋值
console.log(p.count) //正常输出 40

p.price = -10 //报错: 范围在 2000 - 20000
p.price = 4000 //正常赋值
console.log(p.price) //正常输出 4000

Tarea 2:

var emps = [
    {ename:"凯凯1", age: 23, salary:7000, married:true},
    {ename:"凯凯2", age: 33, salary:17000, married:true},
    {ename:"凯凯3", age: 44, salary:9000, married:false},
    {ename:"凯凯4", age: 28, salary:12000, married:true},
    {ename:"凯凯5", age: 35, salary:33000, married:false},
]

// 判断是否所有人都大于30岁
// 判断是否有人工资超过3w
// 找出所有已婚的人
// 把数组映射成html组成的数组, 其中元素样子如下:  注意 已婚 class是ok, 未婚class是err
// <a class='ok'>凯凯1-23-7000</a>

JSCORE05

revisar

  • Configuración precisa de las propiedades de los objetos

    • escribible: si se puede escribir

    • enumerable: si se puede atravesar

      • En Google Chrome, las propiedades no transitables son 浅色

    • configurable: si se puede reconfigurar, si el atributo se puede eliminar

    • valor: valor por defecto

    • get: propiedad calculada, el valor es 函数, pero () se puede activar cuando no se usa

    • establecer: oyente, convertir una propiedad en un oyente, asignación de monitor

  • 3 métodos de activación de la función

    • llamar: activar la función inmediatamente; ejecutar temporalmente la función en el objeto - modificar este punto;

      • Parte del parámetro, paso 1 por 1

    • aplicar: activar la función inmediatamente; ejecutar temporalmente la función en el objeto: modificar este punto;

      • Especial: la parte del parámetro se pasa en una matriz

    • bind: la función no se activará; guarde los parámetros y este puntero en la función misma y devuelva la función vinculada; se puede activar en cualquier momento en el futuro --延时执行

  • función de flecha

    • A partir 格式de lo anterior, se proporciona un método de escritura de funciones anónimas más simple:() =>{}

    • Dos azúcares sintácticos:

      • Solo hay un parámetro, () se puede omitir: x => { return x * 2 }

      • El cuerpo de la función tiene solo una línea, {return } omita:x => x * 2

    • El punto de esta palabra clave

      • la función es esta: 运行时el objeto donde se encuentra楠姐.打亮亮()

      • El esto de la flecha: 声明时el objeto donde se encuentra -- fijo, nunca cambiando

      • Constructor's this( new): el objeto construido

        • new implícitamente hace 3 cosas:

          • var this = {};

          • this.__proto__ =函数.prototype

          • return this

      • En modo estricto, el this de la función

        • Si se llama directamente globalmente, esto apunta a indefinido

  • Funciones de orden superior para arreglos

    • 高阶函数: otras funciones se utilizan en la función

    • cada: Verdadero si cada elemento satisface la condición, similar a AND lógico &&

    • algunos: verdadero si al menos un elemento cumple la condición, similar a lógico o ||

    • filtro: obtenga los elementos que cumplen las condiciones 过滤y combínelos en una nueva matriz

    • mapa: mapeo Al atravesar cada elemento, después del procesamiento, el valor de retorno se forma en una nueva matriz;

      • Escenario de uso: convertir datos en cadena HTML

Operación

<!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>作业</title>
</head>
​
<body>
  <script>
    var p = {
      pname: 'iPhone',
      _count: 5,
      _price: 9999,
      c() { return this._count },
      // get: 变身成计算属性, 使用时不需要()
      get d() { return this._count },
      get count() { return this._count }
    }
​
    // 使用时:
    console.log(p.c())
    console.log(p.d)
    console.log(p.count)
​
​
​
​
    // count: 对赋值进行检查 -- 改造成  监听器
    Object.defineProperty(p, 'count', {
      get() { return this._count },
      // set: 设置.  用于把属性改为赋值监听器
      set(value) {
        if (value >= 0 && value <= 100000) {
          // 把正确的值保存下来
          // count属性已经被转换成监听器, 不再具有保存的能力
          // 需要额外制作一个属性, 来存储数据
          // 属性名: 可以随便起, 但是见名知意是最佳的选择
          this._count = value
        } else {
          throw Error('数量赋值范围错误:' + value)
        }
      }
    })
​
    // p.count = -10 //报错
​
    p.count = 40
    // 读取 p._count 可以读取到值, 但是对于用户的观感不好
    // 用户的感觉:  存储在 count 属性里
    // 用户应该觉得: 从 p.count 读取更合理
    console.log(p.count);
​
    // defineProperties: 可以同时完成 price和count的制作
    Object.defineProperty(p, 'price', {
      get() { return this._price },
      set(value) {
        if (value >= 2000 && value <= 20000) {
          this._price = value
        } else {
          throw Error('价格赋值错误:' + value)
        }
      }
    })
​
    // p.price = -100
    p.price = 3000
    console.log(p.price);
  </script>
</body>
​
</html>
<!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>作业</title>
</head>
​
<body>
  <script>
    var emps = [
      { ename: '凯凯1', age: 23, salary: 7000, married: true },
      { ename: '凯凯2', age: 33, salary: 17000, married: true },
      { ename: '凯凯3', age: 44, salary: 9000, married: false },
      { ename: '凯凯4', age: 28, salary: 12000, married: true },
      { ename: '凯凯5', age: 35, salary: 33000, married: false },
    ]
​
    // 判断是否所有人都大于30岁
    var a = emps.every(value => value.age > 30)
    console.log(a ? '都大于30' : '非都大于30');
​
    // 判断是否有人工资超过3w
    var a = emps.some(value => value.salary > 30000)
    console.log(a ? '有超过3w' : '没有超过3w');
​
    // 找出所有已婚的人
​
    // value.married == true:   真==真 , 返回真; 麻烦没必要
    var a = emps.filter(value => value.married)
    console.log(a);
​
    // 把数组映射成html组成的数组, 其中元素样子如下:  注意 已婚 class是ok, 未婚class是err
    // <a class='ok'>凯凯1-23-7000</a>
    var a = emps.map(value => {
      return `<a class='${value.married ? 'ok' : 'err'}'>${value.ename}-${value.age}-${value.salary}</a>`
    })
​
    console.log(a)
  </script>
</body>
​
</html>

para cada

<!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>foreach</title>
</head>
​
<body>
  <script>
    // foreach: 属于数组的高阶函数, 其功能非常简单: 简单的遍历数组, 没有返回值
    var nums = [11, 22, 33, 44, 55, 66, 77]
​
    // 遍历数组的4种方式
​
    // 最原始:
    for (let i = 0; i < nums.length; i++) {
      console.log(i, nums[i]);
    }
​
    // 简化版:  for..in   非数组独有, 是遍历对象的公用方法
    for (let i in nums) {
      console.log(i, nums[i]);
    }
​
    // ES6提供了专门遍历数组的 for..of
    // 用于直接遍历值, 不读取序号
    for (let value of nums) {
      console.log(value);
    }
​
    // 形参, 声明的变量: 都是自定义的
    // var/function/let/const/class: 声明自定义变量
​
    // forEach: 数组的高阶函数, 单纯遍历没有返回值
    nums.forEach((value, index, array) => {
      console.log(index, value);
    })
​
    // 计算出 nums 中元素的总和
    var a = 0
    for (const value of nums) {
      a += value
    }
    console.log(a);
​
    var a = 0
    // 得益于语法糖的存在, forEach完成一些简单的循环, 更加简洁
    nums.forEach(value => a += value)
    console.log(a);
​
    var products = [
      { pname: "iPhone1", price: 8999, count: 4 },
      { pname: "iPhone2", price: 7999, count: 1 },
      { pname: "iPhone3", price: 6999, count: 6 },
      { pname: "iPhone4", price: 5999, count: 8 },
    ]
    // 计算出所有商品的总金额
    var a = 0
    products.forEach(value => a += value.price * value.count)
    console.log(a);
  </script>
</body>
​
</html>

reducir

<!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>reduce</title>
</head>
​
<body>
  <script>
    // reduce: 合并数组数据, 遍历数组的元素, 把处理后的返回值累加在一起
    var nums = [11, 22, 33, 44, 55, 66, 77, 88]
​
    // 把 数组的所有元素 累加在一起
    // a : 相当于捐款箱, 收集每次累加的结果, 然后交给下一个元素
    // 参数2: 0 是a的初始值, 即第一次循环时的初值
    var s = nums.reduce((a, value) => {
      return a + value
    }, 0)
​
    // 每次遍历, 都会把结果传递给 下一次的参数1, 即a
​
    console.log(s);
​
    var products = [
      { pname: "iPhone1", price: 8999, count: 4 },
      { pname: "iPhone2", price: 7999, count: 1 },
      { pname: "iPhone3", price: 6999, count: 6 },
      { pname: "iPhone4", price: 5999, count: 8 },
    ]
​
    // reduce的流程
    // 1个雪糕 -> 家乐(吃一口) -> 思琪(吃一口) -> 波波(吃一口) -> 最终返回 雪糕棍
    var s = products.reduce((a, value) => {
      return a + value.price * value.count
    }, 0)
    // 首次1: a = 0,  累加第一个商品的数量x单价, 传递给下一次循环
    // 第2次: a = 上一次的返回值, 累加当前的, 再传给下一次
    // 第3次: a = 上一次的返回值, 累加当前的, 再传给下一次
    // ...
    // 最终reduce的结果就是 最后一次的 返回值
​
    console.log(s);
​
  </script>
</body>
​
</html>

let/const

<!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>let_const</title>
</head>
​
<body>
  <script>
    // let/const: 都是 ES6 中推出的新特性, 用来声明变量
    // 特征1: 没有全局变量污染, 存储在 script 作用域中
    // 特征2: 没有声明提升(不准确) -- 作者设定了 暂存死区 的概念
​
    // 没声明a: 报错 a is not defined
    // let声明的变量: 有声明提升, 阅读报错发现--知道a的存在
    // 报错: cannot access 'a' before initialization
    //      不能    访问    a  在  初始化代码 之前
    // 准确解释: let 提升了, 但是在声明代码行执行之前, 一直处于暂存死区状态 -- 无法使用 
    // 作者想法: 没有去掉声明提升, 但是利用报错强制用户必须在声明之后再使用变量 -- 效果相当于没有声明提升
    let a
    console.log(a);
​
    // const: 常量,  声明时必须赋值, 之后就无法重新赋值
    const PI = 3.14
    // const A  //必须赋值, 否则报错
​
    // PI = 999 //无法重新赋值
​
    // 注意: 常量的值如果是对象类型, 可以修改
    const 家乐的女孩 = { name: '古力娜扎', hair: '黑色' }
    // 对象特殊: 不更换地址, 可以修改其中的值
    家乐的女孩.hair = '金黄色'
    家乐的女孩.age = 33
​
    console.log(家乐的女孩);
​
    // 不允许换人, 指向其他内存地址
    // 家乐的女孩 = { name: "迪丽热巴" }
​
  </script>
</body>
​
</html>

La forma de proteger el objeto.

<!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>保护对象的方式</title>
</head>
​
<body>
  <script>
    // defineProperty: 操作方式更加 细致, 可以配置每个属性
    // 当前学习的: 直接配置整个对象 而非某个属性 -- 影响范围广
​
    'use strict'
​
    var emp = { ename: "凯凯", age: 33 }
​
    // 修改操作有: 增删改
​
    // 让对象无法 增加 属性
    // prevent阻止 Extensions扩展
    // Object.preventExtensions(emp)
​
    // 不可 增删
    // seal: 密封
    // Object.seal(emp)
​
    // 不可 增删改
    // freeze: 冻结
    Object.freeze(emp)
​
    // emp.wife = '迪丽热巴'
    // delete emp.age
    emp.age = 49
    console.log(emp);
  </script>
</body>
​
</html>

expansor de matriz

<!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>数组的展开语法</title>
</head>
​
<body>
  <script>
    // 来自 ES6 的新增语法糖: 展开语法
    var a = [11, 22, 33, 767, 77, 88, 88]
    // ... 运算符: 去掉 数组的 []
    var b = [44, 55, ...a]
​
    console.log(b);
​
    // max: 的参数只能是 1个1个的, 不接数组类型
    // ES6之前:  Math.max.apply(0, a)
    // ES6之后: ... 来去掉[], 把数组里面的东西拿出来
    var m = Math.max(...a)
    console.log(m);
  </script>
</body>
​
</html>

Sintaxis de expansión para objetos

<!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>对象的展开语法</title>
</head>
​
<body>
  <script>
    var a = { x: 10, y: 20 }
​
    var b = { y: 30, z: 40 }
​
    // ... : 去掉对象/数组的 外层括号
    // 同名的属性, 后写的覆盖先写的
    var c = { w: 100, ...a, ...b }
    // 相当于: { w:100, x: 10, y: 20, y: 30, z: 40 }
​
    console.log(c);
  </script>
</body>
​
</html>

parámetros restantes

<!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>剩余参数</title>
</head>

<body>
  <script>
    // ES6之前: 通过 arguments 来使用函数的 不固定数量的参数
    // arguments的缺点:
    // - 隐藏的变量
    // - 类型是 类数组, 不具备数组的各种方法

    // ES6之后: 允许用 ... 来表示接受剩余参数
    function show(...args) {
      // 习惯上, 变量名叫 args, 名字随便
      console.log(arguments);
      console.log(args);
      // args: 数组类型, 可以用数组的方法
      args.push(1111)
    }

    show(11, 22, 33, 44, 55)

    // 剩余参数
    // ...: 代表剩余参数, 存储剩下的 没有专门声明参数的
    function showGirls(主食, ...菜品) {
      console.log(主食);
      console.log(菜品);
    }

    showGirls('米饭', '炒菜', '海鲜汤', '炒肉')
  </script>

  <script>
    // ...: 固定运算符
    // nums: 自定义变量, 名字无所谓
    // ... 就代表把收到的所有参数, 保存到后方的变量里(数组类型)
    function show(x, ...nums) {
      console.log('nums:', nums);
      // nums = [2, 3, 4]
      // nums[0]: 数组的下标取值, 获取数据
    }

    function show(x, y, ...nums) {
      console.log('x:', x);
      console.log('nums:', nums);
    }

    show(1, 2, 3, 4)
  </script>
</body>

</html>

valor por defecto del parámetro

<!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>参数的默认值</title>
</head>

<body>
  <script>
    // ES6的 函数参数增强特征: 可以为函数的参数设置默认值
    function show(name = '家乐') {
      // 相当于: var name = '家乐'
      // 如果传参了:  name = '思琦'
      console.log(name);
    }

    show() // 没有传递参数, 则 采用默认值
    show('思奇') // 如果传递参数, 则 使用传递的值
  </script>
</body>

</html>

desestructuración de matrices

<!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>数组解构语法</title>
</head>

<body>
  <script>
    // 解构语法: 可以快速从数组中抓取元素 保存到变量里
    var skills = ['唱', '跳', 'rap', '打篮球']
    // 保存到不同的变量里
    let s1 = skills[0]
    let s2 = skills[1]
    let s3 = skills[2]
    let s4 = skills[3]

    // 解构语法:
    let [q, w, e, r] = skills

    console.log(q, w, e, r);

    // 练习
    var r1 = [10, 20, 50] // 分别存储到变量  x, y, z 中

    var [x, y, z] = r1
    console.log(x, y, z);

    // 可选解构
    var names = ['凯凯', '楠楠', '亮亮', '铭铭']
    //             n1     n2             n3
    var [n1, n2, , n3] = names  //不想解构的, 可以省略不写
    console.log(n1, n2, n3);

    // 灵活用法: 互换变量的值
    var yy = 100
    var rr = 200;

    // [yy, rr] = [200, 100]

    // 先组合出一个数组 [rr, yy] == [200, 100]
    // 然后解构
    [yy, rr] = [rr, yy] // = [200, 100]
    console.log(yy, rr);
  </script>
</body>

</html>

deconstrucción de objetos

<!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>对象解构语法</title>
</head>

<body>
  <script>
    // 
    var emp = {
      ename: "家乐",
      age: 18
    }

    // 传统写法
    var ename = emp.ename
    var age = emp.age

    // 解构语法
    var { ename, age } = emp
    console.log(ename, age);

    // 练习
    var p1 = { pname: "iPhone", price: 9999, count: 5 }
    // 把属性读取出来, 保存在变量里
    var { count, pname } = p1
    // 对象类型:无序的
    console.log(count, pname);

    // 起别名
    var p2 = { pname: "mike", count: 10 }

    // count -> c2
    var { count: c2 } = p2
    console.log(c2);
  </script>
</body>

</html>

deconstrucción compleja

<!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>复杂解构</title>
</head>

<body>
  <script>
    var emp = {
      ename: '家乐',
      age: 23,
      skills: ['唱', '跳', 'rap', '篮球'],
      love: ['杨洋', '王一博', '胡歌']
    }

    // 把内容解构出来
    var { ename, age: eage, skills: [q, w, e, r], love } = emp

    console.log(ename, eage, q, w, e, r, love);

    var iPhone = {
      maker: "Apple",
      price: 9999,
      tags: ['高刷', 'iOS', '最佳cpu'],
    }

    // 
    var { maker, price: p_price, tags: [tag1, tag2, tag3] } = iPhone

    console.log(maker, p_price, tag1, tag2, tag3);
  </script>
</body>

</html>

deconstrucción de parámetros

<!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>函数的参数解构</title>
</head>

<body>
  <script>
    // 计算 立方体的 体积
    // 参数解构: 收到对象类型的参数, 直接解构
    function volume({ x, y, z }) {
      // 解构出来再用
      // const { x, y, z } = rect
      console.log(x * y * z);
      // console.log(rect.x * rect.y * rect.z);
    }

    volume({ x: 10, y: 20, z: 30 })


    var emps = [
      { ename: '凯凯1', age: 23, salary: 7000, married: true },
      { ename: '凯凯2', age: 33, salary: 17000, married: true },
      { ename: '凯凯3', age: 44, salary: 9000, married: false },
      { ename: '凯凯4', age: 28, salary: 12000, married: true },
      { ename: '凯凯5', age: 35, salary: 33000, married: false },
    ]
    // map: 把数组映射成 HTML 代码
    var a = emps.map(value => {
      return `<a class='${value.married ? 'ok' : 'err'}'>${value.ename}-${value.age}-${value.salary}</a>`
    })

    // 利用解构简化:
    var a = emps.map(value => {
      const { ename, age, salary, married } = value

      return `<a class='${married ? 'ok' : 'err'}'>${ename}-${age}-${salary}</a>`
    })

    // 参数解构: 参数解构, 需要用() 包围, 防止歧义
    var a = emps.map(({ ename, age, salary, married }) => {
      return `<a class='${married ? 'ok' : 'err'}'>${ename}-${age}-${salary}</a>`
    })

    console.log(a)

    var products = [
      { price: 1000, count: 4, pname: '凯凯1' },
      { price: 2000, count: 7, pname: '凯凯2' },
      { price: 1500, count: 6, pname: '凯凯3' },
      { price: 1200, count: 1, pname: '凯凯4' },
    ]
    // 过滤出总价格大于 4000 的项目:  filter
    var a = products.filter((value) => value.price * value.count > 4000)

    var a = products.filter(({ price, count }) => price * count > 4000)

    // 别名:
    var a = products.filter(({ price: p, count: c }) => p * c > 4000)
    
    console.log(a);
  </script>
</body>

</html>

sintaxis de clase

propiedad estática

<!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>class语法</title>
</head>

<body>
  <script>
    // class语法: 从 Java 语言中出现
    // JS最初开发的时候, 作者认为 Java 的class语法过于庞大, 所以设计了更加简单的 万物皆对象/构造函数 语法

    // 随着时间的发展: JS竟然一跃成为 非常火的语言, 广受关注
    // 群众的呼声: 希望引入 Java 中更加强大的 class 语法, 在 2015 年 的 ES6 中引入了 class 语法 -- 对于会java的程序员很友好

    // 但是: 尴尬的情况 -- 传统的JS程序员比较守旧, 排斥 class 语法
    // 所以: 目前class好用 但是 用的少

    // 对象类型: 在js中
    var emp = {
      ename: "凯凯",
      age: 22,
      phone: '18800120033'
    }

    console.log(emp);

    // 关键词 class 用于声明 类(java的称呼)
    class Emp1 {
      // static: 称为静态属性(java的称呼)
      // 特点: 存储在对象中, 可以直接使用
      static ename = '凯凯'
      static age = 22
      static phone = '19900120033'
    }
    // 本质上是 JS 的函数
    console.dir(Emp1);

    console.log(Emp1.ename, Emp1.age, Emp1.phone);
  </script>

  <script>
    // JS 的对象
    var math = {
      PI: 3.1415,
      LN2: 0.69314,
      E: 2.718,
      LN2: 0.693
    }

    // 改造成: class 的写法, 名字不能重复, 所以叫 math1
    class math1 {
      // 在JS中, 结尾分号可以省略
      static PI = 3.1415;
      static LN2 = 0.69314;
      static E = 2.718;
      static LN2 = 0.693;
    }

    console.dir(math1);
    console.log(math1.PI, math1.LN2);
  </script>
</body>

</html>

Constructor

<!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>构造语法-class</title>
</head>

<body>
  <!-- 
    总结:
    在 JS中制作一个构造函数, 需要两步:
    - 构造函数本身
    - 构造函数的原型 prototype 中添加共享方法  (需要程序员会原型)

    在 java中制作一个构造函数
    - constructor: 固定的名称, 放构造函数
    - 不需要会原型, 就能制作出完美的构造函数 --(对java程序员极具吸引力)
   -->


  <script>
    // JS的构造函数: 分两部分书写
    // 1. 生成对象 -矩形
    function Rect(x, y) {
      // this是什么?  new触发, 当前生成的对象, 此处就是r1
      this.x = x
      this.y = y
    }

    // 2. 原型中存储共享的方法
    // JS程序员必须懂原型, 才能写出构造函数
    Rect.prototype.area = function () {
      return this.x * this.y
    }

    Rect.prototype.perimeter = function () {
      return (this.x + this.y) * 2
    }

    var r1 = new Rect(10, 30)
    console.dir(Rect);
    console.log(r1);
  </script>

  <script>
    // java的构造函数 -- 精髓
    class Rect1 {
      // java的class中, 不需要function关键词, 就能声明函数
      // 关键词,不可修改: constructor, 固定名称, 称为 构造方法
      // 当 new 运算符时, 自动触发
      constructor(x, y) {
        console.log('constructor: 被触发');
        this.x = x
        this.y = y
      }

      // 在java中, 书写的所有方法, 都会 `自动` 放到原型里
      area() {
        return this.x * this.y
      }

      // get关键词: 变身为计算属性, 使用时不用() 能自动触发
      get perimeter() {
        return (this.x + this.y) * 2
      }
    }

    var r2 = new Rect1(20, 50)
    console.dir(Rect1); //查看 prototype 属性
    console.log(r2);

    console.log(r2.area());
    // 由于 是 get 计算属性, 所以不用() 自动就能触发
    console.log(r2.perimeter);
  </script>
</body>

</html>

heredar

<!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>继承</title>
</head>

<body>
  <script>
    // 面向对象开发的 三大特征: 封装 继承 多态
    // 封装: 利用{} 把一些代码括起来, 形成一个整体, 以后可以复用
    //       在JS中的具体表现:  函数

    // 继承: 当使用对象的一个属性时, 自身没有, 则到父中查找
    //       在JS中的具体表现:  原型链

    // 多态: 同一个构造函数生成的对象, 对象可以自定义. 效果如下:
    // 自身有用自己的, 自身没有用父的 -- 龙生九子,各有不同
    var emp = { age: 99 }
    emp.__proto__.age = 18
    console.log(emp.age);
    console.log(emp);

    class A {
      show() {
        console.log('我是A');
      }
    }

    // extends: 继承.  本质上把原型链 指向 A,  认A做父
    class B extends A { }

    console.dir(B); //查看原型 prototype
    var b = new B()
    b.show()
  </script>
</body>

</html>

polimorfismo

<!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>多态</title>
</head>

<body>
  <script>
    class A {
      constructor(x, y) {
        this.x = x
        this.y = y
      }

      area() {
        return this.x * this.y
      }
    }
    // B继承A, 可以使用A的东西
    class B extends A {
      // java的称呼: 重写 -- 书写一个与父中相同的函数
      // 根据原型链的就近原则: B中有area, A中也有area
      // 优先使用 B中的area : 自己有用自己的
      area() {
        // java提供了关键词 super: 代表父元素, 即A
        console.log(super.area())

        console.log('我是B中的area');
      }
    }

    var b = new B(10, 50)
    console.log(b);
    console.log(b.area());
  </script>
</body>

</html>

resumen de la clase

clase es javaun conjunto de gramáticas del idioma, especialmente bueno para hacer构造函数

但是: En el desarrollo JS real, las funciones tradicionales se usan más y las clases se usan menos

  • Sugerencia: conocer primero

  • Realmente interesado: sintaxis de clase JS de video de búsqueda de Baidu

preguntas de tarea

var products = [
  { pname: "iPhone1", price: 8999, count: 4, checked:true },
  { pname: "iPhone2", price: 7999, count: 1, checked:true },
  { pname: "iPhone3", price: 6999, count: 6, checked:false },
  { pname: "iPhone4", price: 5999, count: 8, checked:true },
]

// 计算出 checked 为 true, 即 勾选状态 为真的 商品总价格,  --- 关联以后的 购物车制作
// 分别用foreach 和 reduce 两种方式实现
// 使用参数的解构语法书写
var obj = {
    nickname: "睡懵的渣皇",
    rid: 8922441,
    roomName: "有梦想谁都了不起!!",
    tags:['颜值', '帅气逼人', '直播达人']
}

// 把 obj 中的变量都解构出来,  rid 别名为 roomId.   tags解构成 t1 t2 t3 
// JS的构造函数如下, 修改成 class 语法
function Cube(width, length, height){
    this.width = width
    this.length = length
    this.height = height
}

Cube.desc = '立方体'

Cube.prototype.volume = function (){
    return this.width * this.length * this.height
}

Cube.prototype.area = function (){
    const {width:w, height:h, length:l} = this
    return (w*h + w*l + h+l)*2
}

Cube.prototype.perimeter = function (){
    const {width:w, height:h, length:l} = this
    return (w+h+l)*4
}

var c1 = new Cube(100, 40, 22)

console.log(Cube.desc)

console.log(c1.volume())
console.log(c1.area())
console.log(c1.perimeter())

JSCORE06

revisar

  • Funciones de orden superior para arreglos

    • cada: juzgar que 每一个los elementos en la matriz cumplen las condiciones. Similar a lógico y, solo lo verdadero es verdadero

    • some: determina 至少有一个si los elementos de la matriz cumplen las condiciones. Similar a lógico o, es verdadero si es verdadero

    • filter: Filtrar Formar una nueva matriz de elementos que cumplan las condiciones

    • map: Mapeo. Procesa los datos de la matriz y devuelve el valor para formar una nueva matriz. Especialmente adecuado para datos->HTML

    • forEach: simplemente itera a través de la matriz. No devuelve ningún valor

      • ES6 proporciona: for...of también puede atravesar rápidamente la matriz

    • reducir: inducción Después de atravesar los elementos en la matriz uno por uno, redúzcalos a un valor

  • ES6 nueva sintaxis

    • expansor ...

      • ...数组: expandir la matriz, es decir, eliminar []el cerco de la matriz

      • ...对象: Expande el objeto, es decir, elimina {}el entorno del objeto.

    • Sintaxis de mejora de funciones

      • Parámetros restantes: function 函数名(...变量)

        • La variable es de tipo array, que recibe todos los parámetros recibidos, y tiene el argumentsmismo efecto que

      • Valor por defecto del parámetro:function 函数(参数=值)

        • Al usar una función, si no se pasa ningún parámetro, el parámetro usa el valor predeterminado

    • Gramática destructiva

      • Desestructuración de matrices:var [a, b, ,c] = [11, 22, 33, 44]

        • a=11; b=22; c=44

      • Desestructuración de objetos:var {age, salary, sid} = {sid:11, salary:9999, age:33}

        • Sintaxis de alias:var {salary: s} = {salary: 4488}

      • Desestructuración de argumentos para funciones −必须能看得懂

        var obj = {x: 10, y:30, z: 44}
        ​
        function show( {x, y} ){
            return x + y
        }
        ​
        show(obj)
  • sintaxis de clase

    • Sintaxis derivada de Java, particularmente buena para 构造函数 crear

    • Pero: fácil de usar, pero los programadores de JS son más conservadores: la tasa de popularidad no es alta en la actualidad

    • Método de escritura de atributos estáticos:不如JS方便

      // js中
      var emp1 = {ename:'凯凯', age:33}
      emp1.ename
      ​
      // java
      class emp2 {
          static ename = '凯凯';
          static age = 33
      }
      emp2.ename
    • Constructor

      class Emp{
          // 固定名称的函数, 在new 的时候触发
          constructor(x, y){
              this.x = x
              this.y = y
          }
          
          // 全自动操作原型, 把所有的函数自动存储到原型中
          area(){
              return this.x * this.y
          }
      }
      ​
      var e =  new Emp(11,22)
    • Tres características principales de la orientación a objetos:

      • Encapsulación: se utiliza {}para encapsular el código y activarlo en cualquier momento posterior.

        • Rendimiento concreto: función

      • Herencia: La cadena del prototipo apunta a otros objetos, si no la tienes, puedes encontrarla en el prototipo.

      • Polimorfismo: un método que es el mismo que el padre se puede reescribir en el hijo, y se prefiere el que tiene el hijo cuando se usa

        class A{
            show(){
                console.log('我是A')
            }
        }
        ​
        class B extends A{
            // B中可以书写一个同名的 show方法
            // 使用时, 优先使用自身的show方法
            show(){
                console.log('我是B')
                // 关键词: super
                super.show() // 使用父, A的show方法
            }
        }
        ​
        var b = new B()
        b.show() // B自身没有show方法, 则使用父A的 show方法

infierno de devolución de llamada

<!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>回调地狱</title>
</head>
​
<body>
    <!-- 回调地狱: 在JS中进行一些异步操作时(网络操作), 层层嵌套, 会导致代码阅读困难 -->
​
    <!-- 如下场景: 注册操作 -->
    <!-- 1. 先发请求, 验证用户名是否合法 -->
    <!-- 2. 再发请求, 验证邮箱是否合法 -->
    <!-- 3. 再发请求, 验证手机号是否合法 -->
    <!-- 4. 再发请求, 开始注册 -->
​
    <script>
        function register() {
            // 用 定时器 来模拟 延时操作, 0.5 秒完成
            console.log('检查用户名...');
            setTimeout(() => {
                // 通过随机数来 随机决定成功与否
                if (Math.random() > 0.7) {
                    console.log('用户名正确, 开始验证邮箱...');
                    setTimeout(() => {
                        if (Math.random() > 0.7) {
                            console.log('邮箱正确, 开始验证手机号...');
                            setTimeout(() => {
                                if (Math.random() > 0.7) {
                                    console.log('手机号正确, 开始注册...');
                                    setTimeout(() => {
                                        if (Math.random() > 0.7) {
                                            console.log('注册成功');
                                        } else {
                                            console.log('注册失败!');
                                        }
                                    }, 500);
                                } else {
                                    console.log('手机号错误!');
                                }
                            }, 500);
                        } else {
                            console.log('邮箱错误');
                        }
                    }, 500);
                } else {
                    console.log('用户名错误!');
                }
            }, 500);
        }
    </script>
</body>
​
</html>

solución :Promise

Promesa

<!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>Promise</title>
</head>
​
<body>
  <!-- Promise: ES6提供的一个构造函数, 专门解决回调地狱问题 -->
  <!-- 代码量一点都不少, 只是格式上更加容易阅读 -->
  <script>
    // 先练习基本的格式
    // 固定写法, 先抄10遍
    new Promise((resolve, reject) => { }).then(res => { }).catch(err => { })
​
    // 安排工作.做完了.失败了
​
    // Promise: 承诺
    // resolve: 解决
    // reject: 拒绝
    // then: 然后
    // catch: 抓取
    new Promise((resolve, reject) => {
      // 当调用 resolve 时, 会触发 then 中的箭头函数
      // resolve的参数, 会传递给 then 中的箭头函数
      // resolve('调用resolve') // 这代表成功
​
      // reject 会触发 catch, 其参数传递到 catch 中
      reject('调用reject') // 这代表失败
​
      // resolve和 reject 互斥, 同一时间只能触发一种
    })
      .then(res => console.log('res:', res))
      .catch(err => console.log('err:', err))
​
  </script>
</body>
​
</html>

 

<!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>Promise的使用</title>
</head>
​
<body>
  <script>
    // 家乐 学开车
    // 教练: 踩油门 车就能跑;  踩刹车 车就能停
    // 家乐问题: 油门哪来的? 踩油门为什么能跑, 发动机原理是什么?
    // 但是: 家乐应聘当司机
    // 考试题: 说说汽车的原理 -- 面试造火箭 工作拧螺丝
    // 面试考 Promise原理的极少, 但是确实存在 -- 不是课上讲解的
    //  -- 考 3-4年 高级工程师的题 -- 扩展视频
​
    function jiale() {
      return new Promise((resolve, reject) => {
        // 利用定时器模拟异步操作
        setTimeout(() => {
          var a = Math.random()
          if (a > 0.5) {
            resolve('家乐求婚成功:' + a)
          } else {
            reject('家乐被拒绝了:' + a)
          }
        }, 1000);
      })
​
      // return p
    }
​
    // 波波求婚
    function bobo() {
      // prom : 安装 ES6 插件后
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          Math.random() > 0.5 ? resolve('波波求婚成功') : reject('波波失败!')
        }, 1000);
      });
    }
​
    function haoyang() {
      // prom
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          Math.random() > 0.5 ? resolve('浩洋成功求婚') : reject('浩洋失败!')
        }, 1000);
      });
    }
​
    jiale()
      .then(res => {
        console.log('res:', res)
        // 如果成功, 则触发波波的求婚操作
        return bobo()
        // 返回值, 会触发下一次的 .then
      })
      .then(res => {
        console.log('res:', res)
        // 
        return haoyang()
      })
      .then(res => console.log('res:', res))
      .catch(err => console.log('err:', err))
  </script>
</body>
​
</html>

Conceptos probados con frecuencia sobre Promise:

Las promesas 3tienen estados

  • Recién salido: new Promise--pending

  • Después de activar resolver --fulfilled

  • Después de activar el rechazo --rejected

expresión regular

Sitio oficial: Expresiones regulares - JavaScript | MDN

Un conjunto de gramáticas para usar con 字符串formatos de coincidencia parcial

personaje significado
\ Coincide de acuerdo con las siguientes reglas: una barra invertida que precede a un carácter no especial indica que el siguiente carácter es un carácter especial y no se puede interpretar literalmente. Por ejemplo, "b" sin una "" precedente generalmente coincide con una "b" minúscula, es decir, el carácter se toma literalmente sin importar dónde aparezca. Pero si se agrega "" al frente, ya no coincidirá con ningún carácter, sino que representará un límite de carácter . Una barra invertida antes de un carácter especial indica que el siguiente carácter no es un carácter especial y debe tomarse literalmente. Consulte la sección "Escapar" a continuación para obtener más detalles. Si desea pasar cadenas al constructor RegExp, no olvide que las barras invertidas son caracteres de escape en los literales de cadena. Entonces, para agregar una barra invertida al patrón, debe escapar en el literal de cadena. /[a-z]\s/iy new RegExp("[a-z]\\s", "i")crea la misma expresión regular: una \sexpresión que busca cualquier carácter seguido de un carácter de espacio en blanco (ver más abajo) y está dentro del rango az. Para crear una expresión que contenga una barra invertida a través de un literal de cadena para el constructor RegExp, debe escapar tanto en el nivel de cadena como en el nivel de expresión regular. Por ejemplo /[a-z]:\\/i, y new RegExp("[a-z]:\\\\","i")crearía la misma expresión, es decir, coincidiría con cadenas como "C:".
^ Coincide con el comienzo de la entrada. Si el indicador de varias líneas se establece en verdadero, también coincide inmediatamente después de una nueva línea. Por ejemplo, /^A/'A' en "an A" no coincidiría, pero sí 'A' en "An E". Cuando ' ^' aparece como el primer carácter en un patrón de conjunto de caracteres, tiene un significado diferente. La sección Juego de caracteres inverso tiene una introducción detallada y ejemplos.
ps Coincide con el final de la entrada. Si el indicador multilínea se establece en verdadero, también coincide con la posición antes de la nueva línea. Por ejemplo, /t$/no coincidiría con la 't' en "eater", pero coincidiría con la 't' en "eat".
* Coincide con la expresión anterior 0 o más veces. equivalente a {0,}. Por ejemplo, /bo*/coincidiría con 'booooo' en "Un fantasma abucheó" y 'b' en "Un pájaro trinó", pero no coincidiría con "Una cabra gruñó".
+ Coincide con la expresión anterior 1 o más veces. equivalente a {1,}. Por ejemplo, /a+/coincidiría con 'a' en "candy" y todas las 'a's en "caaaaaaaandy", pero no coincidiría con "cndy".
? Coincide con la expresión anterior 0 o 1 veces. equivalente a {0,1}. Por ejemplo, /e?le?/coincide con 'el' en "ángel", 'le' en "ángulo" y 'l' en "oslo". Si le sigue inmediatamente cualquier cuantificador *, +, ? o {} , hará que los cuantificadores se conviertan en no- codicioso (coincide con la menor cantidad de caracteres posible), a diferencia del modo codicioso/\d+/ que se usa de forma predeterminada ( coincide con la mayor cantidad de caracteres posible) /\d+?/. También se usa en aserciones anticipadas, como se describe en las entradas x(?=y)y x(?!y)de esta tabla.
. (punto decimal) de forma predeterminada coincide con cualquier carácter individual excepto nueva línea. Por ejemplo, /.n/coincidiría con 'an' y 'on' en "no, una manzana está en el árbol", pero no con 'no'. Si sel indicador ("dotAll") se establece en verdadero, también coincidirá con las líneas nuevas.
(X) Como muestra el siguiente ejemplo, coincidirá con 'x' y recordará la coincidencia. donde los paréntesis se denominan paréntesis de captura . Los ' ' y ' ' /(foo) (bar) \1 \2/en el patrón coinciden y recuerdan las dos primeras palabras en la cadena "foo bar foo bar". Los y en el patrón indican que las subcadenas coincidentes con el primer y segundo paréntesis capturados, es decir, y , coinciden con las dos últimas palabras de la cadena original. Tenga en cuenta que , , ..., se utilizan en el enlace coincidente de las expresiones regulares. Para obtener más información, consulte la entrada \n más adelante. En la parte de reemplazo de la expresión regular, se debe usar una sintaxis como , , ..., por ejemplo, . Indica la cadena original completa utilizada para la coincidencia.(foo)(bar)\1\2foobar\1\2\n$1$2$n'bar foo'.replace(/(...) (...)/, '$2 $1')$&
(?:X) Coincide con 'x' pero no recuerda la coincidencia. Estos paréntesis se denominan paréntesis de no captura y le permiten definir subexpresiones que se usan con operadores de expresiones regulares. Mira este ejemplo /(?:foo){1,2}/. Si la expresión es /foo{1,2}/, {1,2}solo se aplicará al último carácter 'o' de 'foo'. Si se utilizan paréntesis que no capturan, se {1,2}aplican a toda la palabra 'foo'. Consulte la entrada Uso de paréntesis a continuación para obtener más información .
x(?=y) Coincide con 'x' solo si 'x' va seguido de 'y'. Esto se denomina aserción anticipada. Por ejemplo, /Jack(?=Sprat)/ coincidirá con 'Jack' solo si va seguido de 'Sprat'. /Jack(?=Sprat|Frost)/ coincide con 'Jack' solo si va seguido de 'Sprat' o 'Frost'. Pero ni 'Sprat' ni 'Frost' son parte de los resultados coincidentes.
(?<=y) x Haga coincidir 'x' solo si 'x' está precedido por 'y'. Esto se denomina aserción de búsqueda posterior. Por ejemplo, /(?<=Jack)Sprat/ coincidirá con 'Sprat' solo si está precedido por 'Jack'. /(?<=Jack|Tom)Sprat/ coincide con 'Sprat' solo si está precedido por 'Jack' o 'Tom'. Pero ni 'Jack' ni 'Tom' son parte del partido.
x(?!y) Coincide con 'x' solo si 'x' no va seguido de 'y', lo que se denomina búsqueda de negación anticipada. Por ejemplo, /\d+(?!.)/ coincide con un número solo si el número no va seguido de un punto decimal. La expresión regular /\d+(?!.)/.exec("3.141") coincide con '141' pero no con '3.141'
(?<!*y*)*x* Coincide con 'x' solo si 'x' no está precedido por 'y' Esto se denomina búsqueda de negación inversa. /(?<!-)\d+/Por ejemplo, coincide con un número solo si el número no está precedido por un signo menos . /(?<!-)\d+/.exec('3')Coincide con "3". /(?<!-)\d+/.exec('-3')Debido a que hay un signo menos delante de este número, no coincide.
x|y Coincide con 'x' o 'y'. Por ejemplo, /verde|rojo/ coincide con 'verde' en "manzana verde" y 'rojo' en "manzana roja"
{norte} n es un entero positivo que coincide exactamente con n apariciones del carácter anterior. Por ejemplo, /a{2}/ no coincidirá con la 'a' en "candy", pero coincidirá con todas las a en "caandy" y las dos primeras 'a' en "caaandy".
{norte,} n es un número entero positivo que coincide con al menos n apariciones del carácter anterior. Por ejemplo, /a{2,}/ coincide con "aa", "aaaa" y "aaaaa", pero no con "a".
{Nuevo Méjico} Tanto n como m son números enteros. Coincide con el carácter anterior al menos n y como máximo m veces. Si el valor de n o m es 0, este valor se ignora. Por ejemplo, /a{1, 3}/ no coincide con ningún carácter en "cndy", coincide con la a en "candy", coincide con las dos primeras a en "caandy" y también coincide con las tres primeras en "caaaaaaaandy" a . Tenga en cuenta que al hacer coincidir "caaaaaaaandy", el valor coincidente es "aaa", aunque hay más a en la cadena original.
[xyz\] Una colección de personajes. Coincide con cualquier carácter entre corchetes, incluidas las secuencias de escape . Puede usar un guión (-) para especificar un rango de caracteres. Los símbolos especiales como el punto (.) y el asterisco (*) no tienen un significado especial en un juego de caracteres. No tienen que ser escapados, pero escapar funciona. Por ejemplo, [abcd] es lo mismo que [ad]. Ambos coinciden con la 'b' en "brisket" y ambos coinciden con la 'c' en "city". /[az.]+/ y /[\w.]+/ coinciden con la cadena "test.i.ng".
[^xyz\] Un juego de caracteres inverso. Es decir, coincide con cualquier carácter que no esté entre corchetes. Puede usar un guión (-) para especificar un rango de caracteres. Cualquier personaje normal funciona aquí. Por ejemplo, abc y ac son lo mismo. Coinciden con la 'r' en "brisket" y también con la 'h' en "chop".
[\b\] Coincide con un retroceso (U+0008). (No confundir con \b.)
\b 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。(不要和[\b]混淆了)使用"moon"举例: /\bm/匹配“moon”中的‘m’; /oo\b/并不匹配"moon"中的'oo',因为'oo'被一个“字”字符'n'紧跟着。 /oon\b/匹配"moon"中的'oon',因为'oon'是这个字符串的结束部分。这样他没有被一个“字”字符紧跟着。 /\w\b\w/将不能匹配任何字符串,因为在一个单词中间的字符永远也不可能同时满足没有“字”字符跟随和有“字”字符跟随两种情况。备注: JavaScript的正则表达式引擎将特定的字符集定义为“字”字符。不在该集合中的任何字符都被认为是一个断词。这组字符相当有限:它只包括大写和小写的罗马字母,十进制数字和下划线字符。不幸的是,重要的字符,例如“é”或“ü”,被视为断词。
\B 匹配一个非单词边界。匹配如下几种情况:字符串第一个字符为非“字”字符字符串最后一个字符为非“字”字符两个单词字符之间两个非单词字符之间空字符串例如,/\B../匹配"noonday"中的'oo', 而/y\B../匹配"possibly yesterday"中的’yes‘
\c*X* 当X是处于A到Z之间的字符的时候,匹配字符串中的一个控制符。例如,/\cM/ 匹配字符串中的 control-M (U+000D)。
\d 匹配一个数字。``等价于[0-9]。例如, /\d/ 或者 /[0-9]/ 匹配"B2 is the suite number."中的'2'。
\D 匹配一个非数字字符。``等价于[^0-9]。例如, /\D/ 或者 /[^0-9]/ 匹配"B2 is the suite number."中的'B' 。
\f 匹配一个换页符 (U+000C)。
\n 匹配一个换行符 (U+000A)。
\r 匹配一个回车符 (U+000D)。
\s 匹配一个空白字符,包括空格、制表符、换页符和换行符。等价于[ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。例如, /\s\w*/ 匹配"foo bar."中的' bar'。经测试,\s不匹配"\u180e",在当前版本Chrome(v80.0.3987.122)和Firefox(76.0.1)控制台输入/\s/.test("\u180e")均返回false。
\S 匹配一个非空白字符。等价于 [^\f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。例如,/\S\w*/ 匹配"foo bar."中的'foo'。
\t 匹配一个水平制表符 (U+0009)。
\v 匹配一个垂直制表符 (U+000B)。
\w Coincide con un solo carácter (letra, dígito o guión bajo). equivalente a [A-Za-z0-9_]. Por ejemplo, /\w/coincide con 'a' en "apple", '5' en "$5.28" y '3' en "3D".
\W Coincide con un carácter que no es una palabra. equivalente a [^A-Za-z0-9_]. Por ejemplo, /\W/o /[^A-Za-z0-9_]/coincide con '%' en "50%.".
\*norte* En una expresión regular, devuelve la subcadena que coincide con la última n-ésima subcaptura (el número de capturas se cuenta entre paréntesis de apertura). Por ejemplo, /apple(,)\sorange\1/coincide con 'manzana, naranja' en "manzana, naranja, cereza, melocotón".
\0 Coincide con el carácter NULL (U+0000), no seguido de otro decimal, porque \0<digits>es una secuencia de escape octal.
\xhh Coincide con un carácter representado por un número hexadecimal de dos dígitos (\x00-\xFF).
\uhhhh Coincide con una unidad de código UTF-16 representada por un número hexadecimal de cuatro dígitos.
\u{hhhh}或\u{hhhhh} (Solo cuando se establece el indicador u) Coincide con un carácter Unicode representado por un número hexadecimal.

partido habitual

<!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>正则表达式</title>
</head>
​
<body>
  <script>
    // 正则表达式: Regular Expression  简称 RegExp
    // 正则不是 JS 的特性, 而是一套通用的 字符串模糊 匹配方案
    // 官方提供了一个字典: 一些字符 对应 一些特殊的说明含义
​
    // \d  : 匹配一个数字
​
    // 要求: 查找到 字符串中所有的 数字
​
    // match: 匹配.字符串的一个方法,用来查询出符合正则表达式要求的字符
    // 参数要求是正则表达式, 正则要求存放在 // 中
    // 类似于 字符串要放在 引号中;  "\d" -字符串   /\d/ -正则    
​
    // g: global 全局 ; 是正则表达式的修饰符, 代表匹配出所有符合条件的
    var words = '家乐兜里有500元, 花了100, 还剩400. Nice!'
​
    // 找到英文字母
    // []: 代表自定义的字符集合
​
    // 查询出中文:  中文在Unicode字典中的编码是 \u4e00 开始, \u9fa5 结束
    var a = words.match(/[\u4e00-\u9fa5]/g)
    console.log(a);
​
    // i : ignore 忽略, 属于正则修饰符, 代表 忽略大小写
    var a = words.match(/[a-z]/ig)
    console.log(a);
​
    var a = words.match(/[a-zA-Z]/g)
    console.log(a);
​
    var a = words.match(/[a-z]/g)
    console.log(a);
​
    var a = words.match(/\d/g)
    console.log(a);
  </script>
</body>
​
</html>

reemplazo regular

<!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>正则替换</title>
</head>

<body>
  <script>
    // replace: 替换
    var words = '家乐欠债500元, 已还100, 还剩400未还'

    // 把数字变为 *
    // 把参数1 正则匹配到的字符, 替换成 参数2
    var a = words.replace(/\d/g, '*')
    var a = words.replace(/家乐/, '**')
    console.log(a);

    // 进阶用法: 搭配捕获组使用
    var phone = '18879798888'
    // 要求 把手机号中间 4位, 变为 ****
    var a = phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3')
    // 猜: $1 和 $3 是什么意思?
    // () :称为捕获组, 用于抓取出匹配到的指定内容
    // {n} : 有n个   例如 \d{3} 代表3个数字
    // $n: 代表 第n个捕获组中的值, 例如 $1就是第一个小括号里的值
    console.log(a);
    // 练习: 改为 188-7979-8888

    var phone = '18879798888'
    var a = phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3')
    console.log(a);

    // 颠倒位置 18879798888 -> 18888887979
    var a = phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1$3$2')
    //                    第1个()  第2个   第3个
    console.log(a);

  </script>
</body>

</html>

validación periódica

<!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>正则验证</title>
</head>

<body>
  <script>
    // 通过浏览器 收集用户输入的号码
    var p = prompt('请输入手机号')
    console.log('p:', p)

    // 判定是否为手机号:  11位数字  1开头   第二位 3-9
    // ^ : 代表字符串的开头
    // $ : 代表字符串的结尾
    var phone_reg = /^1[3-9]\d{9}$/
    // 使用正则 来 验证字符串
    var a = phone_reg.test(p) // test:验证,测试
    console.log(a ? '是手机号' : '不是手机号');
  </script>
</body>

</html>

Construcción regular

<!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>正则的构造方式</title>
</head>

<body>
  <script>
    // 所有的字面量, 都有对应的构造方式 -- 本体
    // new Array();  new Object();
    // new Number();  new String()
    // new RegExp()   创造正则

    var words = '亮亮99 涛涛88 家乐59 波波dd'

    // 构造方式创建正则
    // JS的 \ 是转义符, \d 转义成 d
    // 需要用 \\d 来转义成 普通的 \d
    var r = new RegExp('\\d\\d', 'g')
    var a = words.match(r)
    console.log(a)

    var a = words.match(/\d\d/g)
    console.log(a);
  </script>
</body>

</html>

Acerca de JS Avanzado

En general, hay dos partes:

  • Teoría: 面试必考como un programador JS maduro debe conocer la teoría

    • impulso de declaración

    • Cierre

    • prototipo

    • Objetos de configuración precisa

  • Aplicación práctica

    • ES5 nuevas características

    • Nuevas funciones de ES6: se pueden usar en el desarrollo real

      • expansor

      • deconstruir

      • mejora de la función

      • Regular

Supongo que te gusta

Origin blog.csdn.net/cxl1191628698/article/details/128170783
Recomendado
Clasificación