对象方法
Object.getOwnPropertyDescriptor
ES5 方法
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }
描述对象的enumerable属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。
Object.getPrototypeOf
使用Object.getPrototypeOf()可以方便地取得一个对象的原型
Object.is
ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
Object.assign
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
第一个参数是目标对象,后面的参数都是源对象
检测属性的方法
in运算符、hasOwnPreperty()和propertyIsEnumerable()
- in:对象的自有属性或者继承属性返回true,不考虑是否可枚举
var o={x:1}
"x"in o;//true:"x"是o的属性
"y"in o;//false:"y"不是o的属性
"toString"in o;//true:o继承toString属性
- hasOwnPreperty:仅检测到自有属性返回true
var o={x:1}
o.hasOwnProperty("x");//true:o有一个自有属性x
o.hasOwnProperty("y");//false:o中不存在属性y
o.hasOwnProperty("toString");//false:toString是继承属性
- propertyIsEnumerable:只有检测到是自有属性且属性可枚举时它才返回true。
遍历属性的方法
- ==for...in==循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
- ==Object.keys==返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名
- ==Object.getOwnPropertyNames==返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名
- ==Object.getOwnPropertySymbols==返回一个数组,包含对象自身的所有 Symbol 属性的键名
- ==Reflect.ownKeys==返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
其他方法
- Object.values()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
- Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
创建对象和ES6的Class
1. 工厂模式
代码:
function createPerson(name,age,job) {
var o = newObject();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
};
return o;
}
var person1 = createPerson ("Nicholas",29,"SoftwareEngineer");
var person2 = createPerson("Greg",27,"Doctor");
解决了创建多个相似对象的问题,但却没有解决对象识别的问题
2. 构造器模式
特点:
- 没有显示的创建对象
- 直接将属性和方法赋给this
- 没有return
new的过程
- 创建一个新的对象
- 将构造函数的作用域赋给新对象,即改变this指向,指向新对象
- 执行构造函数中的代码(给新对象添加属性和方法)
- 返回新对象
/**
* 构造函数
*/
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () { alert(this.name); };
// 与声明函数在逻辑上是等价的,
// 导致每次new一个对象时都会创建新的sayName
this.sayName = newFunction("alert(this.name)");
this.sayNameFunc = sayNameFunc;
}
// 该方式导致作用域混乱
function sayNameFunc(){ alert(this.name); }
var person1 = newPerson("Nicholas", 29, "SoftwareEngineer");
var person2 = newPerson("Greg", 27, "Doctor");
console.log(person1.sayName === person2.sayName); // false
问题:
对于方法的创建比较麻烦,1、如果在构造函数内部直接赋值到this,会造成每次new时都创建一个新Function的情况;2、如果将函数声明放到外部,又会出现作用域问题。
3. 原型模式(构造函数+原型)
构造函数+原型
- 每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象
- 这个对象的用途是==包含==可以由特定类型的所有==实例共享==的属性和方法。
4. ES6的Class
- ES6 的类,完全可以看作构造函数的另一种写法。
- 类的数据类型就是函数,类本身就指向构造函数
- 类的所有方法都定义在类的prototype属性上面。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
- constructor: 构造方法
- this:实例对象
class Person {
constructor(){
console.log(this.__proto__.constructor === Person); // ture
}
}
const person1 = new Person();
console.log(person1.constructor === Person.prototype.constructor); // true
console.log(person1.__proto__.constructor === Person.prototype.constructor); // true
console.log(person1.__proto__.constructor === Person); // true
console.log(person1.__proto__.constructor.prototype === Person.prototype); // true
console.log(Person === Person.prototype.constructor); // true