前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JS对象 - this - 原型 - 可迭代器 - Symbol - 继承

JS对象 - this - 原型 - 可迭代器 - Symbol - 继承

原创
作者头像
云台大树
修改2021-08-25 11:29:46
1.2K0
修改2021-08-25 11:29:46
举报

this

Usually a method needs to do something with the object it was called on. When a function is called as a method—looked up as a property and immediately called, as in object.method()—the binding called this in its body automatically points at the object that it was called on.

You can think of this as an extra parameter that is passed in a different way. If you want to pass it explicitly, you can use a function’s call method, which takes the this value as its first argument and treats further arguments as normal parameters.

箭头函数的this绑定该函数定义时候所在的作用域指向的对象, call apply bind 不改变它绑定的this

因此用箭头函数来声明对象的方法时候,一定要小心里面的this陷阱,而且箭头函数不能用做构造函数!

代码语言:txt
复制
// 该箭头函数绑定f里的this,通过call,改变f的this
let aobj = {
  a: 22
}
function f() {
  let obj = {
    say: () => {
      console.log(this == aobj); // --> true
      console.log(this.a); // -->22
    },
    a: 3
  };
  obj.say();
}
f.call(aobj);

prototype

most objects also have a prototype. A prototype is another object that is used as a fallback source of properties. When an object gets a request for a property that it does not have, its prototype will be searched for the property, then the prototype’s prototype, and so on.

Object.prototype()获取对象的原型对象

Functions derive from Function.prototype, and arrays derive from Array.prototype.

Constructors (all functions, in fact) automatically get a property named prototype, which by default holds a plain, empty object that derives from Object.prototype.

Class declarations currently allow only methods—properties that hold functions—to be added to the prototype

这是一个很好的例子,用于练习原型链和this

代码语言:txt
复制
let map = { one: true, hasOwnProperty: true};
console.log(Object.getPrototypeOf(map).hasOwnProperty.call(map, "one")); // → true

Symbol

Symbols are values created with the Symbol function. Unlike strings, newly created symbols are unique—you cannot create the same symbol twice

代码语言:txt
复制
let sym = Symbol("name");
console.log(sym == Symbol("name"));
// → false
function Rabbit() {};
Rabbit.prototype[sym] = 55;
let blackRabbit = new Rabbit();
console.log(blackRabbit[sym]);
// → 55
console.log(blackRabbit);

multiple symbols may have the same name, but their values are always different and unique.

Being both unique and usable as property names makes symbols suitable for defining interfaces that can peacefully live alongside other properties, no matter what their names are

代码语言:txt
复制
const toStringSymbol = Symbol("toString");
Array.prototype[toStringSymbol] = function() {
  return `${this.length} cm of blue yarn`;
};
console.log([1, 2].toString());
// → 1,2
console.log([1, 2][toStringSymbol]());
// → 2 cm of blue yarn

It is possible to include symbol properties in object expressions and classes by using square brackets around the property name

代码语言:txt
复制
let stringObject = {
  [toStringSymbol]() { return "a jute rope"; }
};
console.log(stringObject[toStringSymbol]());
// → a jute rope

iterator interface

The object given to a for/of loop is expected to be iterable. This means it has a method named with the Symbol.iterator symbol. 该迭代器有next函数,该函数每次返回一个对象

对象具有一个名叫Symbol.iterator的方法,就是可迭代对象.该方法要返回一个迭代器对象!

迭代器对象要有next方法

代码语言:txt
复制
// 调用可迭代对象string的迭代器接口方法产生一个迭代器!
let okIterator = "OK"[Symbol.iterator]();
console.log(okIterator.next());
// → {value: "O", done: false}
console.log(okIterator.next());
// → {value: "K", done: false}
console.log(okIterator.next());
// → {value: ?developer/article/1867330/undefined, done: true}

下面的例子是使用Symbol.iterator实现自己的可迭代对象

代码语言:txt
复制
class Matrix {
  constructor(width, height, element = (x, y) => ?developer/article/1867330/undefined) {
    this.width = width;
    this.height = height;
    this.content = [];

    for (let y = 0; y < height; y++) {
      for (let x = 0; x < width; x++) {
        this.content[y * width + x] = element(x, y);
      }
    }
  }
  // getter
  get(x, y) {
    return this.content[y * this.width + x];
  }
  // setter
  set(x, y, value) {
    this.content[y * this.width + x] = value;
  }
  // 为Matrix类添加一个迭代器接口方法!
  // 把迭代器接口分到外面写更好,这样解耦了!
  [Symbol.iterator]() {
    return new MatrixIterator(this);
  }
}

class MatrixIterator {
  constructor(matrix) {
    this.x = 0;
    this.y = 0;
    this.matrix = matrix;
  }

  next() {
    if (this.y == this.matrix.height) return {done: true};

    let value = {x: this.x,
                 y: this.y,
                 value: this.matrix.get(this.x, this.y)};
    this.x++;
    if (this.x == this.matrix.width) {
      this.x = 0;
      this.y++;
    }
    return {value, done: false};
  }
}
// Matrix.prototype[Symbol.iterator] = function() {
//   return new MatrixIterator(this);
// };
let matrix = new Matrix(2, 2, (x, y) => `value ${x},${y}`);
for (let {x, y, value} of matrix) {
  console.log(x, y, value);
}
// → 0 0 value 0,0
// → 1 0 value 1,0
// → 0 1 value 0,1
// → 1 1 value 1,1
let matrixIterator = matrix[Symbol.iterator]();
console.log(matrixIterator.next()); 
console.log(matrixIterator.next());
console.log(matrixIterator.next());
// → { value: { x: 0, y: 0, value: 'value 0,0' }, done: false }
// → { value: { x: 1, y: 0, value: 'value 1,0' }, done: false }
// → { value: { x: 0, y: 1, value: 'value 0,1' }, done: false }

继承

代码语言:txt
复制
class SymmetricMatrix extends Matrix {
  constructor(size, element = (x, y) => ?developer/article/1867330/undefined) {
    // 构造函数里需要调用super()
    super(size, size, (x, y) => {
      if (x < y) return element(y, x);
      else return element(x, y);
    });
  }

  set(x, y, value) {
    super.set(x, y, value);
    if (x != y) {
      super.set(y, x, value);
    }
  }
}

let matrix = new SymmetricMatrix(5, (x, y) => `${x},${y}`);
console.log(matrix.get(2, 3));
// → 3,2

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com