对象
__proto__ 属性
let obj = {};obj.__proto__ = 5; // 分配一个数字alert(obj.__proto__); // [object Object] — 值为对象,与预期结果不同
对象和 Map 的差异:
- Map 可以使用对象作为键
- 迭代的顺序与插入值得顺序相同,与普通的Object不同,Map保留了此顺序 ```javascript let john = { name: “John” };
// 存储每个用户的来访次数 let visitsCountMap = new Map();
// john 是 Map 中的键 visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
```javascriptlet john = { name: "John" };let jo = { age: 23 };let visitsCountObj = {}; // 尝试使用对象visitsCountObj[john] = 123; // 尝试将 john 对象作为键visitsCountObj[jo] = "dd";console.log(visitsCountObj[john]);// 是写成了这样!alert( visitsCountObj["[object Object]"] );
原型、继承
设置 原型的限制:
- 引用不能形成闭环。如果我们试图在一个闭环中分配proto,JavaScript 会抛出错误。
- proto的值可以是对象,也可以是null。而其他的类型都会被忽略。
for … in 循环
for..in循环也会迭代继承的属性
let animal = {eats: true};let rabbit = {jumps: true,__proto__: animal};// Object.keys 只返回自己的 keyalert(Object.keys(rabbit)); // jumps// for..in 会遍历自己以及继承的键for(let prop in rabbit) alert(prop); // jumps,然后是 eats
使用 obj.hasOwnProperty(key) 过滤掉继承的属性
let animal = {eats: true};let rabbit = {jumps: true,__proto__: animal};for(let prop in rabbit) {let isOwn = rabbit.hasOwnProperty(prop);if (isOwn) {alert(`Our: ${prop}`); // Our: jumps} else {alert(`Inherited: ${prop}`); // Inherited: eats}}
F.prototype
默认的 ‘prototype’ 是一个只有属性的 constructor 的对象,属性 constructor 指向函数自身
function Rabbit() {}// by default:// Rabbit.prototype = { constructor: Rabbit }alert( Rabbit.prototype.constructor == Rabbit ); // true
如果F.prototype是一个对象,那么new操作符会使用它为新对象设置[[Prototype]]
let animal = {eats: true};function Rabbit(name) {this.name = name;}Rabbit.prototype = animal;let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animalalert( rabbit.eats ); // true
类
class User {…}构造实际上做了如下的事儿:
- 创建一个名为User的函数,该函数成为类声明的结果。该函数的代码来自于constructor方法(如果我们不编写这种方法,那么它就被假定为空)。
- 存储类中的方法,例如User.prototype中的sayHi。 ```typescript class User { constructor(name) { this.name = name; } sayHi() { alert(this.name); } }
// class 是一个函数 alert(typeof User); // function
// …或者,更确切地说,是 constructor 方法 alert(User === User.prototype.constructor); // true
// 方法在 User.prototype 中,例如: alert(User.prototype.sayHi); // alert(this.name);
// 在原型中实际上有两个方法 alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
```typescript// 用纯函数重写 class User// 1. 创建构造器函数function User(name) {this.name = name;}// 函数的原型(prototype)默认具有 "constructor" 属性,// 所以,我们不需要创建它// 2. 将方法添加到原型User.prototype.sayHi = function() {alert(this.name);};// 用法:let user = new User("John");user.sayHi();
私有的和受保护的属性和方法
通过设置 get 和 set
class CoffeeMachine {_waterAmount = 0;set waterAmount(value) {if (value < 0) throw new Error("Negative water");this._waterAmount = value;}get waterAmount() {return this._waterAmount;}constructor(power) {this._power = power;}}// 创建咖啡机let coffeeMachine = new CoffeeMachine(100);// 加水coffeeMachine.waterAmount = -10; // Error: Negative water
