JavaScript Objects
JS 对象是可以包含多个值的变量。这些值以 name: value
对的形式、逗号为分隔符。
在JS中,all data types have a valueOf()
和 toString()
方法.
创建新对象
1.Using an Object Literal
同数组一样,空格和换行不重要。
var person = {firstName:"John", lastName:"Doe", age:50};
var person = {
firstName:"John",
lastName:"Doe",
age:50
};
2.Using the JavaScript Keyword new
var person = new Object();
person.firstName = "John";
person.lastName = "Doe";
person.age = 50;
以上两种方法做的都是一样的事,为了简单、易读和执行速度,选用第一种方法。
3.Using an Object Constructor
有时我们希望使用 an object type,创建多个对象。这时可以使用一个构造函数来创建相同类型的对象。通常将函数名首字母大写,作为使用 new 去调用的提醒。
function Person(first, last, age) {
this.firstName = first;
this.lastName = last;
this.age = age;
}
var myFather = new Person("John", "Doe", 50);
var myMother = new Person("Sally", "Rally", 48);
new 关键字
参看这里解释得简单易懂。
function A (arg) {
var tmp = {}; // 1.创建临时空对象
tmp.prototype = A.prototype // 2.把构造函数的原型赋给临时对象的原型
tmp.arg = arg
return tmp // 3.返回这个临时对象
}
A.prototype = {
prop: propvalue,
func: function(){}
}
构造函数 A 可以简写成:
function A (arg) {this.arg = arg} // this 指向临时对象,与下面解释关键字 this 用法的观点一致
new A('参数')
中的 new 所做的事情就是上面数字标记注释的三个步骤。
this keyword
JS中被称为 this 的东西就是拥有 JS 代码的对象。
默认情况下,this 指的是全局对象 window
。
- 当用在 function, 指的是拥有这个函数的对象。
- 当用在 object, 就是对象本身。
- 当用在 object constructor, is only a substitute(替代) for the new object. 构造函数里的 this 本没有值,当函数被用来创建新的对象时,this 的值变为新对象。
- 还可以在 HTML 元素事件绑定里使用 this,指的是触发事件的 HTML DOM element。(JS Event Order 章节有提到)
- 用在 call、apply 方法时,指向函数的直接调用者
JavaScript Objects are Mutable
JS对象是易变的,由 reference 获取,而不是 value。
var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"}
var x = person;
x.age = 10; // This will change both x.age and person.age
x is not a copy of person. It is person. 它们都指向同一个对象。
JavaScript Object properties
name:value 称为JS对象的 properties 属性。
读取对象的属性有两种方法:objectName.propertyName
或者 objectName["propertyName"]
。
后者也可以使用 expression 表达式:objectName[expression]
,只要表达式被评估是属性的 name。
如果对象中不含要找的属性,则返回 undefined
。
- 添加属性,对已经存在的对象,用获取属性的方法给这个属性赋值即可。
-
删除属性,使用关键字 delete。
delete person.age; // or delete person["age"];
该操作不仅删掉了属性的值,也删掉了属性本身。
delete 操作符
The delete
operator is designed to be used on object properties.
关于返回值:
- 删除成功返回 true,失败返回 false。在
"use strict";
模式下不能删除的情况 raise SyntaxError。 - 删除一个对象里不存在的属性,并没有什么效果,也返回 true。
- 只对自己的属性有效,删除不会影响该对象原型链上的同名属性。
-
任何通过
var
声明的属性,不能被从 global 作用域或一个函数的 local 作用域里删除:- 不通过
var
声明的属性可以被删除 - 全局作用域不能删除函数
- 作为一个对象的函数可以被删除
- 不通过
- 使用
let
或const
声明的属性不能被删除(from the scope within which they were defined)。 - 不可配置的属性不能被删除。包括,内置对象
Math
,Array
,Object
,以及通过Object.defineProperty(...,...,{configurable: false})
方法创建的不可配置属性。delete
删除没有什么效果,返回 false。
JavaScript Object methods
JS对象要执行的操作,存放在 properties 里作为 function definition 函数定义。
- 创建对象的方法:
methodName : function() { code lines }
- 获取对象的方法:
objectName.methodName()
- 给 existing 对象添加新方法:
objectName.methodName = function() { code lines };
在 methodName property 后面加 ()
括号,这个属性将作为一个函数来执行。如果不加后面的 ()
,则返回 function definition 函数定义。
JavaScript Object Prototypes
在 JS 中,函数是一个包含属性和方法的 Function 类型的对象。而原型(Prototype)就是 Function 类型对象的一个属性。
- 在函数定义时就包含了 prototype 属性,其初始值是一个空对象。
- 原型用于保存对象的共享属性和方法。
- 原型的属性可以有默认值。
- 使用对象构造函数,创建对象的原型。如上面创建对象第3个例子中,构造函数就是 person 对象的原型。
用 new 关键字创建的对象,继承该类对象的原型,如 new Date(),继承 Date.prototype
。
原型链 prototype chain 的根节点是 Object.prototype
(其包含方法 toString(),这也是为什么所有 js 变量都可使用 toString 方法)。
当我们尝试获取一个对象的属性发现不存在时,JS 会检测该对象的原型上是否存在那个属性。
给对象添加属性或方法
- add new properties (or methods) to an existing object. 给现存的对象添加属性或方法,很简单,上面有讲。
- add new properties (or methods) to all existing objects of a given type.
- add new properties (or methods) to an object prototype.
后两种情况可以使用(1)直接把新的属性或方法写在构造函数里。(2)使用 prototype 属性。
person.prototype.nationality = "English";
person.prototype.name = function() {
return this.firstName + " " + this.lastName;
};
注意:最好不要改变标准JS对象的原型。若创建新属性,首先确认原型里不存在。
for…in 语句
以 arbitrary order (任意顺序)遍历一个对象的除Symbol以外的可枚举属性。对于每一个 distinct 不同的属性,该语句都可以被执行。
用法:
for (variable in object) {...
// 在一趟遍历中每一个不同的属性名称被赋值给 _variable_
}
操作‘对象属性’可用的方法
Object.getOwnPropertyNames(obj)
和Object.keys(obj)
,两者返回 obj 对象中由所有属性的名称(string)所组成的数组。{}
空对象返回[]
空数组。注意:两者 IE9 以下都不支持。obj.hasOwnProperty(prop)
,该方法返回 boolean 值,表示 obj 对象中是否含有指定的属性。Object.values()
返回指定对象自身可枚举的属性值组成的列表。
var otherStoreUrl = { // 其他在线平台店铺链接,最多填3个
one: '',
two: '',
three: '',
}
let tmpArry = []
// 提取值非空的url组成的数组
tmpArry = Object.values(this.otherStoreUrl).filter(ele => ele.length > 1)
对象的复制
1.使用 Object.assign(target, ...sources)
方法返回 target 对象,只复制源对象 property 的值。
- 如果 source 属性值是指向某对象(内嵌子对象)的 reference,将只复制 reference 的值(即,此方法不能做到深度复制,源对象中的子对象属性值变化,会同时改变复制对象中同名子对象的同名属性值)
- 按从左到右的顺序依次复制和 override 属性值(最右边的覆蓋前面所有)
- 不复制 non-enumerable、在原型链上的属性
- 遇到 exception 时中断 copying 任务(如遇到 read-only 的属性时,throw exception)
- sources 值为 null、undefined 的属性将被忽略(从结果里剔除)
2.使用 JSON.parse(JSON.stringify(sourceObj))
可以做到深度复制。跨浏览器,且性能最优。
缺点是任何不符合 JSON 规范的值都将丢失:
- 不能复制属性值为 function 的 属性
- 不能复制属性值为 undefined 的属性(值为 null 可以)
- 属性值为 JS Date 对象的复制结果变为 ISO 标准日期格式(YYYY-MM-DDTHH:mm:ss.sssZ)的字符串
继承
继承是面向对象软件技术中的一个概念,使得复用代码非常容易,缩短开发周期,降低开发费用。
子类继承父类的特征和行为,子类对象(实例)具有父类的所有属性和方法,或子类从父类继承方法,使其具有与父类相同的行为。
原型式/链继承
function myObject(o) { // 1、定义一个函数
function F() {} // 2、在函数中创建一个临时性的构造函数
F.prototype = o; // 3、将函数入参(一个对象)作为这个构造函数的原型
return new F(); // 4、返回这个构造函数的实例
}
let person = {
name: "John",
friends: ["Alice", "Bob"]
};
let anotherPerson = new myObject(person);
anotherPerson.friends.push("Charlie");
console.log(anotherPerson.friends); // ['Alice', 'Bob', 'Charlie']
构造函数继承
在子对象的构造函数中调用父对象的构造函数。具体通过 call()
或 apply()
方法实现。
function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
SuperType.call(this); // 或 SuperType.apply(this, arguments);
}
let instance = new SubType();
console.log(instance.colors); // ["red", "blue", "green"]