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
<!-- ES6之前 --> 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)); <!--//结果--> <!--["name", "height", "age", "constructor", "say", "sex", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]-->3.2 for...in
该方法依次访问一个对象及其原型链中所有可枚举的属性。
const keys = []; for (let key in child) { keys.push(key); } console.log("for...in:", keys); <!--结果:["name", "height", "age", "sex"]-->3.3 Object.keys(o)
该方法返回对象 o 自身包含(不包括原型中)的所有可枚举属性的名称的数组。
console.log("Object.keys:", Object.keys(child)); <!--结果:["name", "height", "age"]-->3.4 Object.getOwnPropertyNames(o)
该方法返回对象 o 自身包含(不包括原型中)的所有属性(无论是否可枚举)的名称的数组。
console.log( "Object.getOwnPropertyNames:", Object.getOwnPropertyNames(child) ); <!--结果:["name", "height", "age"]-->4、创建新对象
4.1 Object 构造函数
<!--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__
<!--Object.create函数--> // 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--> 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)
<!-- 结果--><!--constructor: ƒ People()--><!--__proto__:--><!--constructor: ƒ Object()--><!--hasOwnProperty: ƒ hasOwnProperty()--><!--isPrototypeOf: ƒ isPrototypeOf()--><!--propertyIsEnumerable: ƒ propertyIsEnumerable()--><!--toLocaleString: ƒ toLocaleString()--><!--toString: ƒ toString()--><!--valueOf: ƒ valueOf()--><!--__defineGetter__: ƒ __defineGetter__()--><!--__defineSetter__: ƒ __defineSetter__()--><!--__lookupGetter__: ƒ __lookupGetter__()--><!--__lookupSetter__: ƒ __lookupSetter__()--><!--get __proto__: ƒ __proto__()--><!--set __proto__: ƒ __proto__()-->
console.log(p.__proto__ === p.constructor.prototype)console.log(p.__proto__ === Object.getPrototypeOf(p))console.log(p.constructor.prototype === Object.getPrototypeOf(p))<!-- 结果--><!--true->
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函数原型的原型: 值为nullconsole.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.prototypeconsole.log("Object.__proto__.__proto__:",Object.__proto__.__proto__ === Object.prototype);//Object对象-原型-原型-原型 : 值为nullconsole.log("Object.__proto__.__proto__.__proto__:",Object.__proto__.__proto__.__proto__);console.log("-Object构造函数属性---");//Object对象-构造函数:Functionconsole.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.prototypeconsole.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__);
>参考链接
hao-kuai
还未添加个人签名 2018.10.22 加入
还未添加个人简介











评论