面向对象:
三大特点: 封装,继承,多态
封装: 创建一个对象,集中保存现实中一个事物的属性和功能
3种:
1. 对象直接量:
何时使用: 只创建一个单独的对象
已经知道所有属性和功能
2. 用new关键词:
何时使用: 只创建一个单独的对象
在创建时,暂时不知道对象的属性和功能。
3. 构造函数:
何时使用: 反复创建多个相同类型的对象时
如何使用: 2步:
1. 定义构造函数(类型),描述一类对象统一的数据结构
2. 用new实例化构造函数的对象
new: 1. 创建新对象
2. 设置新对象继承构造函数的原型对象
3. 用新对象调用构造函数,添加属性和方法
4. 返回新对象地址
优: 代码重用
缺: 不能节约内存
继承: 父对象的成员,子对象无需重复创建,就可直接使用。
为什么(优): 代码重用和节约内存
何时使用: 如果多个子对象,拥有相同的属性值和方法时,就都要定义父对象,统一保存一份。
如何使用: js中的继承都是继承原型
原型对象: 集中保存同一类型的多个子对象,共有的属性值和方法的父对象
创建:定义构造函数时,自动创建
每个构造函数都有一个prototype属性指向该类型的原型对象。
默认:每实例化一个子对象,就自动设置子对象的__proto__继承构造函数的原型对象
原型链: 由各级父对象逐级继承,形成的链式结构。
原型链: 控制着对象的属性的访问顺序
vs 作用域链: 控制着变量的使用顺序
多态: 同一个方法,在不同情况下,表现出不同的状态
重写(override):如果子对象觉得父对象的成员不好用,可在本地创建同名自有成员,覆盖父对象中的成员
为什么: 表现子对象和父对象之间的差异
1.*****自定义继承:
2.*****ES5
1.*****自定义继承:
1. 仅修改一个对象的父对象:
obj.__proto__=father
问题: __proto__是内部属性,本不能直接使用。
解决:
Object.setPrototypeOf(child,father)
设置child继承father
Object.getPrototypeOf(child)
获得child的父对象
问题: 每次只能修改一个对象的父对象
2. 批量修改所有子对象的父对象:
修改构造函数的原型对象:
构造函数.prototype=father
时机: 在定义完构造函数后,在开始创建第一个子对象之前。
3. 两种类型间的继承:
问题: 两种类型间,有相同的属性和方法
解决: 抽象出一个公共的父类型,集中保存两种类型相同的属性结构和方法
如何实现: 3步:
1. 定义父类型构造函数和原型对象
2. 在子类型构造函数中借用父类型构造函数
如何借用: call和apply
父类型构造函数.apply(this,arguments)
call和apply: 专门用于借用一个函数,并替换函数中的this为指定对象。
何时使用: 今后,只要函数中的this不是想要的,都要用call和apply更换。
鄙视题:call vs apply:
相同: 借用函数,替换this
不同: call要求传入函数的参数必须独立传入。
apply要求传入函数的参数必须放入一个数组或集合中,整体传入
如何使用:
函数.call(
替换this的对象,要传给函数的参数)
3. 让子类型的原型对象继承父类型的原型对象。
Object.setPrototypeOf(
子类型的原型对象,
父类型的原型对象
);
2. *****ES5:
对象的属性:
ES5中提供了对对象属性的保护
命名属性: 凡是可用.直接访问的属性
数据属性: 直接存储属性值的属性
每个数据属性都有四大特性:
value: 实际存储属性值
writable: true/false 是否可修改
enumerable:true/false 是否可遍历
configurable:true/false
是否可修改或删除其他特性
如何读取一个属性的特性:
Object.getOwnPropertyDescriptor(
obj,"属性名"
)//返回一个对象,包含四大特性
特性的默认值:
用传统方式添加的属性,四大特性都是true。
如何设置属性的特性:
Object.defineProperty(obj,"属性名"{
特性:值,
...:...
})
问题: 任何时候都可用defineProperty将特性恢复原样
解决: 修改特性同时,都要将configurable设置为false
configurable一旦被改为false,则不可逆。
访问器属性: 不直接存储属性值,仅提供对其他属性的保护
内部属性: 不允许打.直接访问的属性
比如: class __proto__
严格模式: 比普通的js代码执行要求更严格
为什么: 为了统一开发的写法。
何时使用: 新项目,都要在严格模式下开发
旧项目,逐个功能向严格模式迁移
如何启用: 在当前代码段的顶部加:
"use strict";
规定:
1. 将静默失败,升级为错误!
正课:
1. *****ES5
对象的属性:
数据属性:
四大特性:
value:
writable:
enumerable:
configurable:
传统方式设置的属性,特性的默认值都是true
设置:
Object.defineProperty(obj,"属性名",{
特性:值
})
如果obj中没有指定的属性名,则自动添加同名属性。但是,特性默认都是false!
建议: 用defineProperty添加新属性时,尽量显式定义四大特性
问题: defineProperty依次只能设置1个属性的四大特性。
解决: Object.defineProperties(obj,{
属性:{四大特性},
...:...
})
访问器属性: 不直接保存数据,为其他数据属性提供验证和保护的特殊属性
四大特性:
get:function(){return xxx}
set:function(val){
验证val
xxx=val
}
enumerable:
configurable:
何时使用: 只要用自定义的规则保护属性时,都要用访问器属性
如何使用: 2步:
1. 定义数据属性,实际存储属性值
问题: 使用者可直接操作数据属性,而绕过访问器属性的保护。
解决: 闭包!
2. 定义访问器属性,保护数据属性
只能用defineProperty()
Object.defineProperty(obj,"属性名",{
get:function(){return xxx},
set:function(val){xxx=val},
enumerable:
configurable:
})
get/set方法都不用手动调用:
只要用访问器属性取值时,自动调get()
只要用访问器属性赋值时,自动调set()
set中的参数val,会自动获得要赋的值
构造函数中的访问器属性:
鄙视: 实现一个类型,同时包含public公有属性和private私有属性
private私有属性: 仅在对象内部使用的属性,无法通过.访问到。
public公有属性: 直接用对象.可访问到的属性。
防篡改: 禁止添加,删除,修改对象的属性
1. 防扩展:
每个对象中,都有一个默认的内部属性:
extensible,默认为true,说明随时可扩展新属性。
如果修改extensible属性为false,则禁止扩展新属性
如何修改:
Object.preventExtensions(obj)
阻止对obj对象的一切扩展
问题:只限制添加新属性,不限制删除旧属性
2. 密封: 在防扩展的基础上,修改所有属性的configurable特性为false
如何密封: Object.seal(obj);
将obj对象密封
3. 冻结: 在密封基础上,禁止修改所有属性的值。
Object.freeze(obj);
Object.create():创建一个新对象,继承指定的父对象,同时为新对象扩展新属性
何时使用: 只要基于一个现有父对象,创建一个子对象时。
如何使用:
var child=Object.create(father,{
新属性:{四大特性},
...:...
})
数组API:
1. 判断: 数组中的元素是否符合要求:
arr.every(...):判断arr中所有元素是否都符合要求。
arr.some(...):判断arr中是否包含符合要求的元素。
如何使用:
var bool=arr.every(
function(val,idx,arr){
return 判断条件
}
);
every会用function去arr中每个元素执行检查。只有每个元素的执行结果都为true时,才返回true。只要任意一个不返回true,则every立刻返回false。
说明:
val: 自动获得当前正在检查的元素值
idx: 自动获得当前正在检查的元素位置
arr: 自动获得当前正在检查的数组对象
2.遍历: 对数组中的每个元素执行相同个操作
arr.forEach(...):依次对arr中每个元素执行相同的操作,再保存回原数组。
直接修改原数组
arr.map(...): 依次取出arr中每个元素的值,执行相同操作,再保存到新数组中
不直接修改原数组,返回新数组