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函数原型的原型: 值为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__
);
>参考链接
hao-kuai
还未添加个人签名 2018.10.22 加入
还未添加个人简介
评论