X

曜彤.手记

随记,关于互联网技术、产品与创业

吉 ICP 备10004938-2号

《JavaScript 高级程序设计(第四版)》读书笔记(第 8-11 章)


书接上回,本文为第 8-11 章的笔记。

第 8 章 - 对象、类与面向对象编程

  1. (Page:530)ECMAScript 使用一些内部特性来描述对象属性的特征
let person = {};
Object.defineProperty(person, 'name', {
  writable: false,
  enumerable: false,
  configurable: true,
  value: 'Jason Yu',
});
let foo = {
  name: 'Jason',
}
Object.defineProperty(foo, 'nickname', {
  enumerable: true,
  configurable: true,
  get() { return this.name; },
  set(value) { this.name = value; },
});

// 与上述等价的 ES6 写法;
// let foo = {
//   name: 'Jason',
//   get nickname() { return this.name; },
//   set nickname(value) { this.name = value }
// }
  1. (Page:540)对象操作:
console.log(Object.is(+0, -0));  // false.
console.log(Object.is(+0, 0));  // true.
console.log(Object.is(-0, 0));  // false.
console.log(Object.is(NaN, NaN));  // true.
let person = {
  name: 'Jason',
  age: 27,
};
let { name: personName, age: personAge, job: personJob = 'engineer' } = person;
console.log(personName, personAge, personJob);

- 在解构过程中,如果为了给事先声明的变量赋值,则赋值表达式必须被包含在一对括号中

let personName, personAge, personJob;
let person = {
  name: 'Jason',
  age: 27,
};
({name: personName, age: personAge, job: personJob = 'engineer'} = person);
console.log(personName, personAge, personJob);

- 解构也可以用在函数参数中。

let person = {
  name: 'Jason',
  age: 27,
};
function printPerson(id, { name, age }) {
  console.log(id, name, age);
}
printPerson(1, person);
  1. (Page:563)ECMAScript 实现的几种方式:
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayName = function() {
    console.log(this.name);
  }
}
let p = new Person('Jason', 27);
p.sayName();
console.log(p instanceof Person);  // true.
console.log(p instanceof Object);  // true.

function ObjCreate(o) {
  function F(){};
  F.prototype = o;
  return new F();
}
function Person(name, age) {
  this.name = name;
  this.age = age;
}
Person.prototype = {
  sayName() {
    console.log(this.name);  // stay on the prototype.
  }
};
Object.defineProperty(Person.prototype, 'constructor', {
  enumerable: false,  // keep consistent.
  value: Person,
});
let p = new Person('Jason', 27);
  1. (Page:600)继承
function SuperType(name) {
  this.name = name;
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(name) {
  SuperType.call(this, name);  // keep private members.
}
SubType.prototype = new SuperType();  // inherit common methods.
new SubType('Jason').sayName();
let person = {
  name: 'Jason',
};

let anotherPerson = Object.create(person, {
  name: {
    value: 'Greg',
  }
});
function inheritPrototype(subType, superType) {
  let proto = Object.create(superType.prototype);
  proto.constructor = subType;
  subType.prototype = proto;
}
function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'green'];
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function() {
  console.log(this.age);
}
  1. (Page:622)(语法糖):
class Person {
  constructor(name, nicknames) {
    this.name = name;
    this.nicknames = nicknames;
  }
  sayName() {
    console.log(this.name);
  }
  *sayNicknames() {
    yield* this.nicknames;
  }
  static generatePerson(name, nicknames) {
    return new Person(name, nicknames);
  }
  set inc(value) {  // setter.
    while(value--) {
      this.name += '+';
    }
  }
  get inc() {  // getter.
    return this.name.length - this.name.indexOf('+');
  }
};
Person.tag = 'PersonClass';  // static property.
Person.prototype.rank = 100;  // commom property (anti-pattern).
const p = Person.generatePerson('Jason', ['Jack', 'Jake']);

// 继承;
class Chinese extends Person {
  constructor(name, nickname, age) {
    super(name, nickname);  // will return a "this" of the derived instance.
    this.age = age;
  }
  sayAge() {
    console.log(this.age);
  }
};
const c = new Chinese('Jason', ['Jack', 'Jake'], 27);
c.sayAge();
class Vehicle {
  constructor() {
    console.log(new.target);
    if (new.target === Vehicle) {  // "new.target" points to constructor.
      throw new Error('Error...');
    }
  }
};

第 9 章 - 代理与反射

  1. (Page:661代理
const target = {
  foo: 'bar'
};
const handler = {
  get(target, property, proxy) {
    return target[property];
  },
  set: Reflect.set,
}
const p = new Proxy(target, handler);
p.foo = 'jar';
console.log(p.foo);

// revocable proxy.
const { proxy, revoke } = Proxy.revocable(target, handler);
revoke();  // proxy is invalid after this.

第 10 章 - 函数

  1. (Page:707函数
const factorial = (function f(num) {
  if (num <= 1) {
    return 1;
  } else {
    return num * f(num - 1);
  }
});

- 典型的闭包

function createComparisonFunction(propertyName) {
  return function(x, y) {
    let vA = x[propertyName]; 
    let vB = y[propertyName]; 
    if (vA < vB) {
      return -1l
    } else if (vA > vB) {
      return 1;
    } else {
      return 0;
    }
  }
}

- 对应的作用域链关系

第 11 章 - Promise 与异步函数

  1. (Page:790)Promise:
// Promise.resolve 静态函数是“幂等”的,而 Promise.reject 则不是(参数会被直接作为拒绝理由);
let pA = Promise.resolve(1);
let pB = Promise.resolve(pA);
console.log(pA == pB);  // true.
console.log(pA); // Promise {<fulfilled>: 1}.
pA.then(i => console.log(i));  // 1.
// 几种常见的 reject 情况;
new Promise((resolve, reject) => reject(Error('foo')));
new Promise((resolve, reject) => {
  throw Error('foo');
});
new Promise.resolve().then(() => {
  // this way will create another Promise as a returning result.
  throw Error('foo');
});
new Promise.reject(Error('foo'));
class CancelToken {
  constructor(cancelFn) {
   this.promise = new Promise((resolve, reject) => {
     cancelFn(resolve);
   });
  }
}
function foo(delay) {
  return new Promise((resolve, reject) => {
   const id = setTimeout(() => {
     resolve(delay);
   }, delay);
   const cancelToken = new CancelToken((cancelCb) => {
     // set up when to cancel the promise.
     if (delay > 2000)
      cancelCb();
   });
   // cancel the promise by clearing the timer.
   cancelToken.promise.then(() => {
    clearTimeout(id);
    reject('Canceled');
   });
  });
}
foo(1000).then(v => console.log(v), v => console.log(v));
class TrackablePromise extends Promise {
  constructor(executor) {
    const notifyHandlers = [];
    super((resolve, reject) => {
      return executor(resolve, reject, status => {
        notifyHandlers.map(handler => handler(status));
      });
    });
    this.notifyHandlers = notifyHandlers;
  }
  notify(notifyHandler) {
    this.notifyHandlers.push(notifyHandler);
    return this;
  }
}
  1. (Page:840异步函数
(async function() {
  Promise.reject(1);
  return;
})().catch(() => {});  // "reject" cannot be catched, but "throw".
async function sleep(delay) {
  return new Promise(resolve => setTimeout(resolve, delay));
}
async function bar() {
  await sleep(1500);
  console.log('after sleeping...');
}
bar();


这是文章底线,下面是评论
  暂无评论,欢迎勾搭 :)