对象:most things are objects
-
对象 = 属性 + 方法: 对象包(Object package, 或叫namespace)封装着数据,使得数据的访问和组织简洁;对象常作为数据存储体(data stiores),在网络上运输数据; 对象是一种代码重用的形式(Object package);
-
创建对象的方式:1. 手动创建对象-literal; 2. 实例化创建;3. 其他,如Object.create
-
属性
-
属性 = name(type: string) + descriptor(type: Object)
描述对象包括以下属性:
configuratable enumable value writable get set 数据描述符 √ √ √ √ × × 存取描述符 √ √ × × √ √ -
表示方法: 1. obj.name -- 索引选择元素 2. obj['name'] -- 关联值的名字 // 对象做了字符串到值得映射,数组做了数字到值得映射
-
-
this指向运行时得对象: the current object the code is being written inside;
- this在字面量对象中可能无法发挥优势,但在动态创建的对象中十分有用
- this在运行时绑定,this的值取决于调用它的方式
- 通过this指向的改变,允许一个对象拥有另一个对象的属性和方法
-
对象间的通信: 对象间通过信息传递进行通信。当一个对象需要另一个对象执行一些操作,会调用另一个对象的方法并等待回应(返回值)
链接:对象常用方法
JavaScript: prototype-based language
javascript中每一个对象都有__proto__属性(访问器属性),指向它的原型对象;
每个对象都从原型上继承一个constructor,指向它的构造函数;
每一个构造函数都有prototype属性,值为所有可被继承的属性和方法,即不在prototype属性上的方法是不能被继承的;
当查找对象的属性或方法时会顺着原型链向上查找,直至最顶层null;
javaScript本身没有类的概念,使用原型实现面向对象编程;javaScript中的类本质上是基于prototype的进一步封装
创建构造函数
-
关键词:
箭头函数不能作为构造函数:它没有prototype属性,无法在原型链上实现继承; 它继承this,没有自己的this,无法改变自身的this指向
实例化:构造函数(模板)运行创建实例(对象);在类中,类(模板)的构造函数运行创建实例对象
多态: 不同数据类型的实体提供统一的接口;重写是实现父类与子类间多态的方式,运行时多态:重写同一个方法;重载是一个类里的多态,编译时多态:一个类中同一个方法名接收的参数不同
// old: 手工构造函数
function ConstrutorFunc() {
let obj = {};
obj.name = 'lili',
obj.greeting = function() {console.log('hello')}
return obj;
}
let instance = constructorFunc(); // 使用方式
// new: new封装构造函数
function ConstructorFunc() {
this.name = 'lili';
this.greeting = funtion() {console.log('hello '+ this.name )}
}
let instance = new ConstructorFunc(); // 使用方式;
/** new封装后结构更清晰
* 可见,new做了什么:
* 1. 创建一个{}
* 2. 为该对象添加__proto__属性,属性值为ConstructorFunc.prototype
* 3. 绑定this:将步骤1创建的对象作为this的上下文
* 4. 返回该函数的返回值;若无,返回this
*/
// 结果如下,注意:
(1)this在运行时绑定,所以此处不能直接把greeting里的this.name换成lili;
(2)每创建一遍实例,就会创建一次函数,这不理想(js是动态脚本,要的是轻量方便)。所以我们将方法定义在原型上(.prototype),一次定义便可使用,即可动态扩展;
instance = {
name: 'lili',
greeting: funtion() { console.log('hello ' + this.name) }
}
// 补充: 创建对象的其他方式
let instance = new Object({name: 'lili'});
instance.genter = 'male';
// or
let instance = Object.create(instance1);
构造函数与实例在内存中的位置
-
由上图也可以看出构造函数创建对象和Object.create创建对象的区别:
创建方式 创建结果 添加属性 构造函数创建对象 Object.create创建对象
ES6 类
继承与实例化
| ES5 构造函数实例化 | ES6 类实例化 |
|---|---|
ES6 类与ES5 构造函数相同使用
ES6 类与ES5 构造函数区别
-
类中默认使用严格模式(原因是let x = class className {};class y extends x {};中let不能提升,而这是class提升了就会报错),类中所有方法不可枚举,类必须new来创建;
-
继承的实现
- ES5 继承:先创建子类的实例对象this,再把父类方法绑定到this上
- ES6 继承:先将父类实例对象的属性和方法放到this上(super中实现,但this运行时指向子类实例哦),再使用子类构造函数修改this;子类要想使用this,必须先super()创建父类实例
super
- 作为函数使用,只能在构造函数中使用,代表父类构造函数
- 作为对象使用,代表父类的原型对象(prototype);在静态方法中指向父类
- super必须显示调用,明确是作为函数还是对象,否则会报错
静态属性与私有属性
- 静态属性是类本身的属性,只能在类内部访问,可继承,关键字为static
- 私有属性仅在类内部可使用的属性