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
陷阱,而且箭头函数不能用做构造函数!
// 该箭头函数绑定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
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
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
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
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
方法
// 调用可迭代对象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: undefined, done: true}
下面的例子是使用Symbol.iterator
实现自己的可迭代对象
class Matrix {
constructor(width, height, element = (x, y) => 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 }
继承
class SymmetricMatrix extends Matrix {
constructor(size, element = (x, y) => 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 删除。