JavaScript对象

1、概述

  • 一个对象就是一系列属性的集合
  • 一个属性包含一个名和一个值
  • 一个属性的值可以是函数,该属性也被称为方法
2、对象和属性
  • 一个 javascript 对象有很多属性。
  • 一个对象的属性可以被解释成一个附加到对象上的变量。
  • 对象的属性和普通的 javascript 变量基本没什么区别,仅仅是属性属于某个对象。
  • 属性定义了对象的特征
  • 可以通过点符号或者方括号访问或者设置一个对象的属性
  • 对象的名字(可以是普通的变量)和属性的名字都是大小写敏感
  • 对象中未赋值的属性的值为undefined,而不是null
var myCar = new Object(); myCar.make = "Ford"; myCar.model = "Mustang"; myCar.year = 1969; myCar["make"] = "Ford"; myCar["model"] = "Mustang"; myCar["year"] = 1969;

3、枚举一个对象的所有属性
class Parent { constructor(name) { this.name = name; this.height = name; } say() {} } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } say() {} } Child.prototype.sex = "1"; const child = new Child("child", 10); console.log(child);

3.1 ES5 之前 getOwnPropertyNames
function listAllProperties(o, isEnumerable = false) { //获取所有属性,包含原型链 let objectToInspect; let result = []; for ( objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect) ) { result = result.concat(Object.getOwnPropertyNames(objectToInspect)); } //数组元素去重 const newRes = []; result.forEach((item) => { if (newRes.indexOf(item) === -1) { if (isEnumerable === true) { //保留不可枚举属性 newRes.push(item); } else { //不保留不可枚举属性 o.propertyIsEnumerable(item) && newRes.push(item); } } }); return newRes; } console.log("ES5之前:", listAllProperties(child, true));

3.2 for...in
该方法依次访问一个对象及其原型链中所有可枚举的属性。
const keys = []; for (let key in child) { keys.push(key); } console.log("for...in:", keys);

3.3 Object.keys(o)
该方法返回对象 o 自身包含(不包括原型中)的所有可枚举属性的名称的数组。
console.log("Object.keys:", Object.keys(child));

3.4 Object.getOwnPropertyNames(o)
该方法返回对象 o 自身包含(不包括原型中)的所有属性(无论是否可枚举)的名称的数组。
console.log( "Object.getOwnPropertyNames:", Object.getOwnPropertyNames(child) );

4、创建新对象 4.1 Object 构造函数
const obj1 = new Object(); obj1.name = "zs"; obj1.say = function () { console.log("obj1:", this.name); }; obj1.say(); console.log("obj1:", obj1);

4.2 Object.create()
创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
// const obj2 = Object.create(obj1); // const obj2 = Object.create(Object.prototype); const obj2 = Object.create({}); obj2.name = "zs"; obj2.say = function () { console.log("obj2:", this.name); }; obj2.say(); console.log("obj2:", obj2);

4.3 构造函数
两步来创建对象:
  • 通过创建一个构造函数来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。
  • 通过 new 创建对象实例。
function Person(name) { this.name = name; this.say = function () { console.log("obj3:", this.name); }; }const obj3 = new Person("zs"); obj3.name = "zs"; obj3.say = function () { console.log("obj3:", this.name); }; obj3.say(); console.log("obj3:", obj3);

4.4 字面量
const obj4 = {}; obj4.name = "zs"; obj4.say = function () { console.log("obj4:", this.name); }; obj4.say(); console.log("obj4:", obj4);

4.5 class 创建
class People { constructor(name) { this.name = name; } say() { console.log("obj5:", this.name); } } const obj5 = new People("zs"); obj5.name = "zs"; obj5.say = function () { console.log("obj5:", this.name); }; obj5.say(); console.log("obj5:", obj5);

5、原型
  • JavaScript 常被描述为一种基于原型的语言
  • 每个对象拥有一个原型对象,是隐藏属性
  • 对象以其原型为模板、从原型继承方法和属性。
  • 原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。
  • 这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
5.1 函数对象获取原型
通过 prototype 属性访问原型。该属性定义在 Function 对象上。没有找到相关文档,但是可以通过以下验证
Function.hasOwnProperty("prototype") //结果为 true

  • 每个 JavaScript 函数实际上都是一个 Function 对象实例
  • 构造函数也是函数
function doSomething(){} console.log( doSomething.prototype ); //var doSomething = function(){}; //console.log( doSomething.prototype );

输出结果为
{ constructor: ? doSomething(), __proto__: { constructor: ? Object(), hasOwnProperty: ? hasOwnProperty(), isPrototypeOf: ? isPrototypeOf(), propertyIsEnumerable: ? propertyIsEnumerable(), toLocaleString: ? toLocaleString(), toString: ? toString(), valueOf: ? valueOf() } }

5.2 实例对象获取原型
  • __proto__属性,该方法从 Object.prototype 继承而来
  • Object.getPrototypeOf(obj)方法
  • obj.constructor.prototype,其中 constructor 方法从 Object.prototype 继承而来
function People(){}; const p = new People(); console.log(p.__proto__) console.log(Object.getPrototypeOf(p)) console.log(p.constructor.prototype)console.log(p.__proto__ === p.constructor.prototype) console.log(p.__proto__ === Object.getPrototypeOf(p)) console.log(p.constructor.prototype === Object.getPrototypeOf(p))

6、继承
  • JavaScript没有类,全是 ++对象++
  • 对象的原型叫 ++对象原型++
  • 通过对象创建的叫 ++对象实例++
  • 对象实例的原型是 ++对象原型++ 不是 ++对象++
  • 对象实例的初始属性来自 ++复制、初始化对象属性++ 和 ++继承对象原型/链属性++
6.1 继承方式1:call
//定义父类 function People1(name) { //定义父类属性,每个实例对象值都一样,定义在对象上 this.name = name; } //定义父类方法,每个实例对象执行方法一样,定义在原型上 People1.prototype.say = function () {}; //定义子类 //1、实现属性拷贝和赋值 function Student1(name, age) { //使用this调用父类构造函数,生成对象 People1.call(this, name); //子类属性初始化赋值 this.age = age; } //2、实现原型链指向 /* * //不能直接指向父类原型,因为还要修改原型constructor指向,会破坏父类的原型链 * Student1.prototype = People1.prototype; * */ /* * //父类构造函数需要初始化参数,作为原型来讲还需要提供不必要的参数 * Student1.prototype = new People1(""); * */ // 重新生成一个新的原型对象,防止子类父类原型链互相污染 Student1.prototype = Object.create(People1.prototype); Student1.prototype.constructor = Student1; const people = new People1("ww"); console.log("people:", people); console.log( "people.constructor.prototype:", people.constructor.prototype ); People1.prototype.run2 = function () {}; Student1.prototype.run3 = function () {}; const student = new Student1("zs", 20); console.log("student:", student); console.log( "student.constructor.prototype:", student.constructor.prototype );

6.2 继承方式1:extends
class People2 { constructor(name) { this.name = name; } say = function () {}; } class Student2 extends People2 { constructor(name, age) { super(name); this.age = age; } } const people2 = new People2("ww"); console.log("people2:", people2); console.log( "people2.constructor.prototype:", people2.constructor.prototype ); People2.prototype.run2 = function () {}; Student2.prototype.run3 = function () {}; const student2 = new Student2("zs", 20); console.log("student2:", student2); console.log( "student2.constructor.prototype:", student2.constructor.prototype );

7、 Function 和 Object
  • Object.protype 是顶级原型对象
//Object对象 console.log("Object:", Object); console.log("-Object函数属性---"); //Object函数原型 console.log("Object.prototype:", Object.prototype); //Object函数原型的原型: 值为null console.log( "Object.prototype.__proto__:", Object.prototype.__proto__ ); console.log("-Object对象属性---"); //Object对象-原型 console.log("Object.__proto__:", Object.__proto__); //Object对象-原型-原型 console.log( "Object.__proto__.__proto__:", Object.__proto__.__proto__ ); //Object对象-原型-原型 等于 Object.prototype console.log( "Object.__proto__.__proto__:", Object.__proto__.__proto__ === Object.prototype ); //Object对象-原型-原型-原型 : 值为null console.log( "Object.__proto__.__proto__.__proto__:", Object.__proto__.__proto__.__proto__ ); console.log("-Object构造函数属性---"); //Object对象-构造函数:Function console.log("Object.constructor:", Object.constructor); console.log("-Function构造函数属性---"); //Function函数-原型 console.log("Function.prototype:", Function.prototype); //Function函数-原型-原型 console.log( "Function.prototype.__proto__:", Function.prototype.__proto__ ); //Function函数-原型-原型 等于 Object.prototype 等于 Object.__proto__.__proto__ console.log( "Function.prototype.__proto__:", Function.prototype.__proto__ === Object.prototype ); console.log("-Function对象属性---"); //Function对象-原型 console.log("Function.__proto__:", Function.__proto__); //Function对象-原型 等于 Function.prototype console.log( "Function.__proto__:", Function.__proto__ === Function.prototype ); //Function对象-原型-原型 console.log( "Function.__proto__.__proto__:", Function.__proto__.__proto__ ); //Function对象-原型-原型 等于Function.prototype.__proto__ 等于 Object.prototype 等于 Object.__proto__.__proto__ console.log( "Function.__proto__.__proto__:", Function.__proto__.__proto__ === Function.prototype.__proto__ ); console.log("-Function构造函数属性---"); console.log("Function.constructor:", Function.constructor); console.log( "Function.constructor:", Function.constructor.prototype ); console.log( "Function.constructor:", Function.constructor.prototype === Function.__proto__ );

  • 代码链接-创建对象
  • 代码链接-继承
【JavaScript对象】参考链接
  • 使用对象
  • propertyIsEnumerable
  • Object.create()
  • Object
  • propertyIsEnumerable
  • 对象原型
  • JavaScript 中的继承
  • Function.prototype
  • Function

    推荐阅读