你不知道的javascript上卷(笔记二)

for..of

  • 遍历数组,返回遍历的值(普通对象无法使用)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    var arr = ["one", "two", "three"];
    for(var v in arr) {
    console.log(v); // 0,1,2 返回下标
    }
    for(var v of arr) {
    console.log(v); // "one", "two", "three",返回下标对应的值
    }

Object.assign()

  • Object.assign()方法只会拷贝源对象自身的并且可枚举的属性到目标对象身上(浅复制)
    1
    2
    3
    4
    5
    6
    var o1 = {a: 1};
    var o2 = {b: 2};
    var o3 = {c: 3};
    var newObj = Object.assign({}, o1,o2,o3);
    console.log(newObj); // { a: 1, b: 2, c: 3 }

对象属性描述符

  • Object.defineProperty()添加一个新属性或者修改一个已有属性

    • writable决定是否可以修改属性的值,true表示可以改写
    • configurable决定是否可以使用defineProperty方法来修改属性,把该值修改为false是单向操作
    • enumerable决定是否出现在对象的属性枚举中
  • Object.preventExtensions()禁止一个对象添加新属性

  • Object.seal()会创建一个”密封“的对象,在一个现有的对象上调用Object.preventExtensions()并把所有属性标记为configurable:false
  • Object.freeze()会创建一个冻结对象,在一个现有的对象上调用Object.seal(),并把所有属性标记为writable:false
  • Object.keys()返回一个数组,包含所有可枚举属性,只会查找对象直接包含的属性
  • Object.getOwnPropertyNames()返回一个数组,无论是否可枚举,只会查找对象直接包含的属性
  • Object.setPrototypeOf(Chlid.prototype,Parent.prototype) ES6新增用来修改[[prototype]]关联

    1
    2
    3
    4
    5
    // ES5里的原型继承需要把Chlid.prototype对象关联到Parent.prototype
    Child.prototype = Object.create(Parent.prototype);
    // ES6里可以利用辅助函数Object.setPrototypeOf()
    Object.setPrototypeOf(Chlid.prototype,Parent.prototype);
  • isPrototypeOf()Object.getPrototypeOf()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function Foo(){
    //..
    }
    var a = new Foo();
    // 判断是否出现在[[prototype]]链中
    Foo.prototype.isPrototyoeOf(a); // true 表示Foo.prototype是否出现在a的[[prototype]]链中
    // 直接获得一个对象的[[prototype]]
    Object.getPrototypeOf(a) === Foo.prototype; // true

OO vs OLOO

  • OLOO:面向委托的设计,对象关联(objects linked to other objects)
  • 典型的”原型“面向对象风格

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 定义父类Foo
    function Foo(name) {
    this.name = name;
    }
    // 在Foo的prototype上定义identify方法
    Foo.prototype.identify = function() {
    return "I'm " + this.name;
    };
    // 定义子类Bar
    function Bar(name) {
    Foo.call(this, name);
    }
    // 创建一个新的Bar.prototype对象并关联到Foo.prototype上
    Bar.prototype = Object.create(Foo.prototype);
    // 如果需要可以手动改变Bar.prototype.constructor
    // 定义Bar自己的方法
    Bar.prototype.sayHi = function() {
    console.log("Hi " + this.identify() + "!");
    };
    // 实例化Bar
    var bar1 = new Bar("whiskey");
    bar1.sayHi(); // "Hi I'm whiskey!"
  • OLOO对象关联风格

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 创建Foo对象
    Foo = {
    init: function(name) {
    this.name = name;
    },
    identify: function() {
    return "I'm " + this.name;
    }
    };
    // 通过Object.create创建Bar,把Bar的[[prototype]]委托给Foo
    var Bar = Object.create(Foo);
    // 创建Bar对象之间的方法
    Bar.sayHi = function() {
    console.log("Hi " + this.identify() + "!");
    };
    // 通过Object.create创建bar1,把Bar的[[prototype]]委托给Bar
    var bar1 = Object.create(Bar);
    // 初始化bar1对象,传入name
    bar1.init("whiskey");
    bar1.sayHi(); // "Hi I'm whiskey!"