1. function sayHi() {
    2. console.log(name)
    3. console.log(age)
    4. var name = 'Lydia'
    5. let age = 21
    6. }
    7. sayHi()
    8. // undefined 和 ReferenceError
    1. for (var i = 0; i < 3; i++) {
    2. setTimeout(() => console.log(i), 1)
    3. }
    4. // 3 3 3
    5. for (let i = 0; i < 3; i++) {
    6. setTimeout(() => console.log(i), 1)
    7. }
    8. // 0 1 2
    1. const shape = {
    2. radius: 10,
    3. diameter() {
    4. return this.radius * 2
    5. },
    6. perimeter: () => 2 * Math.PI * this.radius
    7. }
    8. shape.diameter()
    9. shape.perimeter()
    10. // 20
    11. // NaN
    1. console.log(+true)
    2. console.log(!"Lydia")
    3. // 1
    4. // false
    1. let c = { greeting: 'Hey!' }
    2. let d
    3. d = c
    4. c.greeting = 'Hello'
    5. console.log(d.greeting)
    6. // Hello
    1. let a = 3
    2. let b = new Number(3)
    3. let c = 3
    4. console.log(a == b) // true
    5. console.log(a === b) // false
    6. console.log(b === c) // false
    1. class Chameleon {
    2. static colorChange(newColor) {
    3. this.newColor = newColor
    4. return this.newColor
    5. }
    6. constructor({ newColor = 'green' } = {}) {
    7. this.newColor = newColor
    8. }
    9. }
    10. const freddie = new Chameleon({ newColor: 'purple' })
    11. freddie.colorChange('orange')
    12. // TypeError 静态方法
    1. let greeting
    2. greetign = {} // Typo!
    3. console.log(greetign)
    4. // {}
    1. function Person(firstName, lastName) {
    2. this.firstName = firstName;
    3. this.lastName = lastName;
    4. }
    5. const member = new Person("Lydia", "Hallie");
    6. Person.getFullName = function () {
    7. return `${this.firstName} ${this.lastName}`;
    8. }
    9. console.log(Person.getFullName()); // undefined undefined
    10. console.log(member.getFullName()); // TypeError member.getFullName is not a function
    function Person(firstName, lastName) {
      this.firstName = firstName
      this.lastName = lastName
    }
    
    const lydia = new Person('Lydia', 'Hallie')
    const sarah = Person('Sarah', 'Smith')
    
    console.log(lydia)
    console.log(sarah)
    // Person {firstName: "Lydia", lastName: "Hallie"}
    // undefined
    
    function sum(a, b) {
      return a + b
    }
    
    sum(1, '2')
    // "12"
    
    let number = 0
    console.log(number++)
    console.log(++number)
    console.log(number)
    // 0
    // 2
    // 2
    
    function getPersonInfo(one, two, three) {
      console.log(one)
      console.log(two)
      console.log(three)
    }
    
    const person = 'Lydia'
    const age = 21
    
    getPersonInfo`${person} is ${age} years old`
    
    // ["", " is ", " years old"] "Lydia" 21
    // 如果使用标记模板字面量,第一个参数的值总是包含字符串的数组。其余的参数获取的是传递的表达式的值!
    
    function checkAge(data) {
      if (data === { age: 18 }) {
        console.log('You are an adult!')
      } else if (data == { age: 18 }) {
        console.log('You are still an adult.')
      } else {
        console.log(`Hmm.. You don't have an age I guess`)
      }
    }
    
    checkAge({ age: 18 }) // Hmm.. You don't have an age I guess
    
    function getAge(...args) {
      console.log(typeof args)
    }
    
    getAge(21)
    // "object"
    
    function getAge() {
      'use strict'
      age = 21
      console.log(age)
    }
    
    getAge()
    // ReferenceError
    
    const sum = eval('10*10+5')
    // 105
    
    const obj = { 1: 'a', 2: 'b', 3: 'c' }
    const set = new Set([1, 2, 3, 4, 5])
    
    obj.hasOwnProperty('1')
    obj.hasOwnProperty(1)
    set.has('1')
    set.has(1)
    
    // true
    // true
    // false
    // true
    
    const obj = { a: 'one', b: 'two', a: 'three' }
    console.log(obj)
    
    // { a:'three',b:'two'}
    
    for (let i = 1; i < 5; i++) {
      if (i === 3) continue
      console.log(i)
    }
    // 1 2 4
    
    String.prototype.giveLydiaPizza = () => {
      return 'Just give Lydia pizza already!'
    }
    
    const name = 'Lydia'
    
    name.giveLydiaPizza()
    
    // Just give Lydia pizza already!
    
    const a = {}
    const b = { key: 'b' }
    const c = { key: 'c' }
    
    a[b] = 123
    a[c] = 456
    
    console.log(a[b])
    //  a = { '[object Object]':456 } => 456
    
    const foo = () => console.log('First')
    const bar = () => setTimeout(() => console.log('Second'))
    const baz = () => console.log('Third')
    
    bar()
    foo()
    baz()
    
    // First Third Second
    
    <div onclick="console.log('first div')">
      <div onclick="console.log('second div')">
        <button onclick="console.log('button')">
          Click!
        </button>
      </div>
    </div>
    
    //  target => "button"
    
    <div onclick="console.log('div')">
      <p onclick="console.log('p')">
        Click here!
      </p>
    </div>
    
    // "p" "div"
    
    const person = { name: 'Lydia' }
    
    function sayHi(age) {
      console.log(`${this.name} is ${age}`)
    }
    
    sayHi.call(person, 21)
    sayHi.bind(person, 21)
    
    // Lydia is 21
    // sayHi(age) {
    //  console.log(`${this.name} is ${age}`)
    // }
    
    function sayHi() {
      return (() => 0)()
    }
    
    typeof sayHi()
    
    // "number"
    
    const numbers = [1, 2, 3]
    numbers[10] = 11
    console.log(numbers)
    // [1, 2, 3, 7 x empty, 11]
    
    (() => {
      let x, y
      try {
        throw new Error()
      } catch (x) {
        (x = 1), (y = 2)
        console.log(x)
      }
      console.log(x)
      console.log(y)
    })()
    
    // 1 undefined 2
    
    [[0, 1], [2, 3]].reduce(
      (acc, cur) => {
        return acc.concat(cur)
      },
      [1, 2]
    )
    // [1,2,0,1,2,3]
    
    function* generator(i) {
      yield i;
      yield i * 2;
    }
    
    const gen = generator(10);
    
    console.log(gen.next().value);
    console.log(gen.next().value);
    
    // 10
    // 20
    
    const firstPromise = new Promise((res, rej) => {
      setTimeout(res, 500, "one");
    });
    
    const secondPromise = new Promise((res, rej) => {
      setTimeout(res, 100, "two");
    });
    
    Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
    
    // "tow"
    
    let person = { name: "Lydia" };
    const members = [person];
    person = null;
    
    console.log(members);
    // [{ name: "Lydia" }]
    
    const person = {
      name: "Lydia",
      age: 21
    };
    
    for (const item in person) {
      console.log(item);
    }
    
    // "name", "age"
    
    const num = parseInt("7*6", 10);
    // 7
    
    [1, 2, 3].map(num => {
      if (typeof num === "number") return;
      return num * 2;
    });
    // [undefined, undefined, undefined]
    
    function getInfo(member, year) {
      member.name = "Lydia";
      year = "1998";
    }
    
    const person = { name: "Sarah" };
    const birthYear = "1997";
    
    getInfo(person, birthYear);
    
    console.log(person, birthYear);
    
    // { name: "Lydia" } "1997"
    
    function greeting() {
      throw "Hello world!";
    }
    
    function sayHi() {
      try {
        const data = greeting();
        console.log("It worked!", data);
      } catch (e) {
        console.log("Oh no an error:", e);
      }
    }
    
    sayHi();
    // "Oh no an error: Hello world!
    
    function Car() {
      this.make = "Lamborghini";
      return { make: "Maserati" };
    }
    
    const myCar = new Car();
    console.log(myCar.make);
    
    // "Maserati"
    
    (() => {
      let x = (y = 10);
    })();
    
    console.log(typeof x);
    console.log(typeof y);
    
    // "undefined", "number"
    
    class Dog {
      constructor(name) {
        this.name = name;
      }
    }
    
    Dog.prototype.bark = function() {
      console.log(`Woof I am ${this.name}`);
    };
    
    const pet = new Dog("Mara");
    
    pet.bark();
    
    delete Dog.prototype.bark;
    
    pet.bark();
    
    // "Woof I am Mara"
    // TypeError: pet.bark is not a function
    
    const set = new Set([1, 1, 2, 3, 4]);
    
    console.log(set);
    // {1,2,3,4}
    
    // counter.js
    let counter = 10;
    export default counter;
    // index.js
    import myCounter from "./counter";
    
    myCounter += 1;
    
    console.log(myCounter);
    
    // Error
    // 引入的模块是 只读 的: 你不能修改引入的模块。只有导出他们的模块才能修改其值。
    // 当我们给myCounter增加一个值的时候会抛出一个异常: myCounter是只读的,不能被修改。
    
    const name = "Lydia";
    age = 21;
    
    console.log(delete name);
    console.log(delete age);
    
    // false, true
    // delete操作符返回一个布尔值
    // 但是通过 var, const 或 let 关键字声明的变量无法用 delete 操作符来删除
    
    const numbers = [1, 2, 3, 4, 5];
    const [y] = numbers;
    
    console.log(y);
    
    // 1
    
    const user = { name: "Lydia", age: 21 };
    const admin = { admin: true, ...user };
    
    console.log(admin);
    // {name: "Lydia", age: 21,admin: true}
    
    const person = { name: "Lydia" };
    
    Object.defineProperty(person, "age", { value: 21 });
    
    console.log(person);
    console.log(Object.keys(person));
    
    //  { name: "Lydia", age:21 };
    // ["name"]
    
    const settings = {
      username: "lydiahallie",
      level: 19,
      health: 90
    };
    
    const data = JSON.stringify(settings, ["level", "health"]);
    console.log(data);
    
    // "{"level":19, "health":90}"
    
    let num = 10;
    
    const increaseNumber = () => num++;
    const increasePassedNumber = number => number++;
    
    const num1 = increaseNumber();
    const num2 = increasePassedNumber(num1);
    
    console.log(num1); 10
    console.log(num2); 10
    
    const value = { number: 10 };
    
    const multiply = (x = { ...value }) => {
      console.log(x.number *= 2);
    };
    
    multiply(); // 20
    multiply(); // 20
    multiply(value); // 20
    multiply(value); // 40
    
    [1, 2, 3, 4].reduce((x, y) => console.log(x, y));
    // 1 2 undefined 3 undefined 4
    
    // 使用哪个构造函数可以成功继承Dog类?
    class Dog {
      constructor(name) {
        this.name = name;
      }
    };
    
    class Labrador extends Dog {
      // 1 
      constructor(name, size) {
        this.size = size;
      }
      // 2
      constructor(name, size) {
        super(name);
        this.size = size;
      }
      // 3
      constructor(size) {
        super(name);
        this.size = size;
      }
      // 4 
      constructor(name, size) {
        this.name = name;
        this.size = size;
      }
    };
    
    // 选择2
    
    // index.js
    console.log('running index.js');
    import { sum } from './sum.js';
    console.log(sum(1, 2));
    
    // sum.js
    console.log('running sum.js');
    export const sum = (a, b) => a + b;
    
    // running sum.js
    // running index.js
    // 3
    
    // import命令是编译阶段执行的,在代码运行之前。因此这意味着被导入的模块会先运行,而导入模块的文件会后执行。
    // 这是CommonJS中require()和import之间的区别。
    // 使用require(),您可以在运行代码时根据需要加载依赖项。 
    // 如果我们使用require而不是import,running index.js,running sum.js,3会被依次打印。
    
    console.log(Number(2) === Number(2)) // true
    console.log(Boolean(false) === Boolean(false)) // true
    console.log(Symbol('foo') === Symbol('foo')) // false
    console.log(new Number(2) === new Number(2)) // false
    
    const box = { x: 10, y: 20 };
    
    Object.freeze(box);
    
    const shape = box;
    shape.x = 100;
    console.log(shape)
    
    const add = () => {
      const cache = {};
      return num => {
        if (num in cache) {
          return `From cache! ${cache[num]}`;
        } else {
          const result = num + 10;
          cache[num] = result;
          return `Calculated! ${result}`;
        }
      };
    };
    
    const addFunction = add();
    console.log(addFunction(10)); // Calculated! 20
    console.log(addFunction(10));  // From cache! 20
    console.log(addFunction(5 * 2)); // From cache! 20
    
    // module.js 
    export default () => "Hello world"
    export const name = "Lydia"
    
    // index.js 
    import * as data from "./module"
    
    console.log(data)
    // { default: function default(), name: "Lydia" }
    // 使用import * as name语法,我们将module.js文件中所有export导入到index.js文件中,
    // 并且创建了一个名为data的新对象。 在module.js文件中,有两个导出:默认导出和命名导出。
    // 默认导出是一个返回字符串“Hello World”的函数,命名导出是一个名为name的变量,其值为字符串“Lydia”。
    
    // data对象具有默认导出的default属性,其他属性具有指定exports的名称及其对应的值。