0%

学习笔记 2020 10 26

学习笔记 2020-10-26

JavaScript 高级程序设计(第4版) 阅读记录

函数

函数扩展与收集

ECMAScript6 新增了扩展操作符。扩展操作符既可以用于调用函数时传参,也可以用于定义函数参数。

扩展参数
let values = [1, 2, 3, 4];
function getSum() {
  let sum = 0;
  for (let i = 0; i < arguments.length; ++i) {
    sum += arguments[i];
  }
  return sum;
}
console.log(getSum(...values)); // 10

对可迭代对象使用拓展操作符作为一个参数传入,可以将可迭代对象拆分,并将迭代返回的每个值单独传入。

function getProduct(a, b, c = 1) {
  return a * b * c;
}
let getSum = (a, b, c = 0) => {
  return a + b + c;
};
console.log(getProduct(...[1, 2])); // 2
console.log(getProduct(...[1, 2, 3])); // 6
console.log(getProduct(...[1, 2, 3, 4])); // 6
console.log(getSum(...[0, 1])); // 1
console.log(getSum(...[0, 1, 2])); // 3
console.log(getSum(...[0, 1, 2, 3])); // 3
收集参数

在函数定义时,使用扩展操作符可以将不同长度的独立参数组合为一个数组。收集参数前面可以有其余命名参数,但只能作为最后一个参数。

箭头函数也支持收集函数。

函数声明与函数表达式

JS 引擎在代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。函数表达式必须等到代码执行到它,才会在执行上下文中生成函数定义。

因此函数声明在使用它之前是没有问题的,因为函数声明会被提升。

函数作为值

函数可以作为变量传递,也可以被返回。

函数内部

arguments

arguments 对象是一个类数组对象,包含调用参数时传入的所有参数。这个对象只有以 function 关键字定义函数时才会有。

arguments 有一个 callee 属性,指向该 arguments 对象所在函数的指针。

this

在标准函数中, this 引用把函数当成方法调用的上下文对象。

this 引用的值只有在函数被调用时才确定。

箭头函数中的 this 引用的是定义箭头函数的上下文。

caller

ECMAScript5 也会给函数对象上添加一个属性: caller 。这个属性引用调用当前函数的函数。在全局中调用则为 null 。

严格模式下不能访问 arguments.callee ,也不能访问 caller ,不能给函数的 caller 属性赋值。

new.target

ECMAScript6 新增了检测函数是否使用 new 关键字调用的 new.target 属性。如果使用 new 关键字调用,则 new.target 将引用被调用的构造函数,否则为 undefined 。

函数属性与方法

每个函数都有两个属性, length 和 prototype 。length 属性保存函数定义的命名参数的个数。

prototype 属性保存引用类型所有实例方法。在 ECMAScript5 中,该属性是不可枚举的。

函数有两个方法,apply() 和 call() 。这两个方法都会以指定的 this 值来调用函数。区别在于 apply() 只需要最多两个参数,第二个参数可以是数组也可以是 arguments 对象。

ECMAScript5 定义了一个新方法 bind() 。bind() 只会绑定 this 值,并创建一个新的函数实例。

现代 JavaScript 教程

任务

  1. 两个函数—一个对象

    是否可以创建像 new A()==new B() 这样的函数 A 和 B?

    function A() { ... }
    function B() { ... }
    let a = new A;
    let b = new B;
    alert( a == b ); // true

    如果可以,请提供一个它们的代码示例。

    let obj = {};
    function A() { return obj; }
    function B() { return obj; }
    alert( new A() == new B() ); // true
  2. 创建 new Calculator

    创建一个构造函数 Calculator,它创建的对象中有三个方法:

    • read() 使用 prompt 请求两个值并把它们记录在对象的属性中。
    • sum() 返回这些属性的总和。
    • mul() 返回这些属性的乘积。

    例如:

    let calculator = new Calculator();
    calculator.read();
    alert( "Sum=" + calculator.sum() );
    alert( "Mul=" + calculator.mul() );
    function Calculator() {
      this.read = function() {
        this.a = +prompt('a?', 0);
        this.b = +prompt('b?', 0);
      }
      this.sum = function() {
        return this.a + this.b;
      }
      this.mul = function() {
        return this.a * this.b;
      }
    }
  3. 创建 new Accumulator

    创建一个构造函数 Accumulator(startingValue)。

    它创建的对象应该:

    • 将“当前 value”存储在属性 value 中。起始值被设置到构造器 startingValue 的参数。
    • read() 方法应该使用 prompt 来读取一个新的数字,并将其添加到 value 中。

    换句话说,value 属性是所有用户输入值与初始值 startingValue 的总和。

    下面是示例代码:

    let accumulator = new Accumulator(1); // 初始值 1
    accumulator.read(); // 添加用户输入的 value
    accumulator.read(); // 添加用户输入的 value
    alert(accumulator.value); // 显示这些值的总和
    function Accumulator(startingValue) {
      this.value = startingValue;
      this.read = function() {
        this.value += +prompt('new value?', 0);
      }
    }

学习记录

grid 布局

auto-fill 与 auto-fit 的区别:

auto-fill 只会自动控制子元素的大小来实现布局。而 auto-fit 会在父容器有多余宽度的时候拉伸子元素来填满父容器。