理解对象
现代定义对象
let person = {
name: 'js',
age: 66,
sayHello() {
console.log(this.name, this.age);
}
}
对象主要包含两种属性:数据属性(Data Properties)和存取属性(Accessor Properties)
数据属性
数据属性包含一个单独的数据空间,用于数据的读和取。数据属性有四个标志来描述描述它们的行为。
1.Configurable - 配置能力,属性是否被重新定义或者删除、改变属性标志,默认都是true,可直接改变。
2.Enumerable - 枚举能力,属性是否通过for-in循环遍历,默认是true直接遍历出来。
3.Writable - 写入能力,属性是否可改变,重新赋值,默认是true。
4.Value - 值,实际数据的存储位置,读取数据就从这里读取,默认是undefined。
基础练习(突然想起来的东西和本章无关,文科生学工总是不灵活,唉~)
let obj = {
name: 'naruto',
age: 30,
ninjitus:['lashgan','kageihunxin']
}
let js = JSON.stringify(obj) //对象转JSON字符串,这里只能对象,放JSON字符串就乱套了
let jp = JSON.parse(js) //JSON字符串转为JS对象
console.log(jp);
Object.defineProperty()
Object.defineProperty()方法可以配置属性的相关设置,writable设置false,可以禁止修改属性
let person = {
}
Object.defineProperty(person, 'name', {
writable:false,
value: '张三'
})
person.name = '法外狂徒'
console.log(person.name);
存取属性
存取属性:不包含属性值的,而包含属性的一对getter方法和setter方法。
存取属性也包含四个可设置想。有两个和数据属性相同设置项 Configurable和Enumerable不再赘述。不同的为Get和Set。
Get - 读取属性时会调用,默认undefined
Set - 写入属性时会调用,默认undefined
合并对象
在es6中引入了Object.assign()方法,这个方法可以接收一个目标对象,和多个源对象,并且把每个源对象拷贝过来,作为目标对象的属性
对象相等
在es6中判断对象是否相等通过 === 进行,也可以使用Object.is()方法进行判断,如:
console.log(Object.is('2', 2));
console.log(Object.is(2, 2));
对象的创建
创建对象有两个基本的方法:一个是字面量,另一个是构造函数,但是都有着共同的缺点,就是创建多个对象,都会存在大量的重复代码。
工厂设计模式
工厂模式是著名的批量创建对象的设计模式,由于抽象创建特定对象的过程,举个栗子:
function createPerson(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name);
};
return o;
}
let person1 = createPerson("Nicholas", 29, "Software Engineer");
let person2 = createPerson("Greg", 27, "Doctor");
createPerson()方法在接收必要的参数后可以创建特定的对象,避免了创建同一类型对象,只是值不同产生的大量的冗余代码。
构造器模式
构造器:JavaScript原生的构造函数用于创建特定类型的对象,JavaScript也支持自定义构造器。
举例:
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
console.log(this.name);
}
}
let person1 = new Person("Nicholas", 29, "Software Engineer");
let person2 = new Person("Greg", 27, "Doctor");
person1.sayName();
person2.sayName();
这段代码有三个特点
1.没有显示的创建对象
2.属性和方法都直接赋值到对象中
3.没有返回表达式
原型模式
每个方法都被原型属性创建,对象内部包含属性和方法,被特定类型的实例引用,可以直接通过prototype
栗子:
function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
console.log(this.name);
};
let person1 = new Person();
person1.sayName();
let person2 = new Person();
person2.sayName();
原型模式特点
无论方法何时被创建,原型属性也会被创建,原型属性默认会获取构造器属性,比如Person.prototype.constructor会指向Person。当自定义构造器时,原型默认只会获取构造器属性,所有的方法都继承自Object。
继承
很多面向对象语言有,两种继承,一种是方法继承,一种是接口继承,JavaScript不存在接口继承,因为JavaScript不存在方法签名。
原型链
ECMA-262标准规定,在ECMAScript中,原型链作为主要的继承方法
原型链的缺点
原型链是继承能力强大的工具,但也存在问题,主要的问题就是关于原型的引用值的问题。
当使用原型实现继承时,原型实际上也会变成另一种类型的实例对象,这意味着曾经是原型属性,现在是实例对象的属性。
类
在ES6中已经可以使用Class关键字定义类了,可解决前面提到的问题
类的组成
包括:构造方法、实例方法、getter、setter和静态的类方法。
类的构造器
构造器关键字使用在类的定义区间使用,作为类的构造函数。使用方法名构造器,将会向指定的方法发送信号,用新的运算符创建新的实例。类中不是必须要定义构造器。
每次通过 new + 类名 创建对象,内部调用构造函数创建对象,新的创建对象会有属于自己的属性。没有限制新的实例里面添加什么,也没有限制以存在构造函数之后添加成员。
初始化
类初使用new运算符进行初始化会遵循以下几点
1.在内存中创建新的对象
2.这个新对象内部原型指向构造器的原型属性
3.这个构造器的值会赋值给新的对象
4.代码内部构造器会被执行
5.如果构造函数返回一个对象,那么new出来就会返回这个对象,否则会返回这个刚刚被创建的对象
原型方法和存取器
为了实例之间可以分享方法,类的语法定义运行方法在类颞部的原型上定义。
方法也可以定义在别的地方,但成员的数据,如私有和对象不能添加到原型上。
类方法与对象属性一直,这意味着,string、symbol和计算属性值可以作为key。
订阅发布
export default {
datalist: [],
subscribe(callback) {
this.datalist.push(callback)
},
publish(value) {
this.datalist.forEach(callback => {
callback(value)
})
}
}