JavaScript 高级
2 对象高级
2.1 原型链总结
function Foo() {
}
var f1 = new Foo();
var f2 = new Foo();
var o1 = new Object();
var o2 = new Object();
f1、f2 的构造函数是 Foo
f1、f2 的原型是 Foo.prototype
Foo.prototype 的构造函数是 Object
Foo.prototype.constructor === Foo
o1、o2 的构造函数是 Object
o1、o2 的原型是 Object.prototype
Foo、Object 的构造函数是 Function
Foo、Object 的原型是 Function.prototype
Function 的构造函数是 Function
Foo.protype === f1.__proto__
Foo.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
Object.__proto__ !== Object.protype
原型链
f1、f2 --> Foo.prototype --> Object.prototype
o1、o2 --> Object.prototype
Foo --> Function.prototype --> Object.prototype
Object --> Function.prototype --> Object.prototype
Function --> Function.prototype --> Object.prototype
Foo.prototype.constructor === Foo
Object.prototype.constructor === Object
Function.prototype.constructor === Function
Foo.prototype === f1.__proto__
Object.prototype === o1.__proto__
Function.prototype === Function.__proto__
2.2 面向对象继承
① 面向对象语言的继承规则
class User {
}
class VipUser extends User {
}
class NewUser extends User {
}
- 一个父类可以有多个子类,一个子类只能有一个父类
- 子类的实例不但拥有定义在子类上的属性和方法,还继承了定义在父类的属性和方法。
② JS 中继承关系的特点
1. JS 中的对象基于原型继承:对象可以使用原型上的属性和方法,原型链的都可以使用。
2. 如果构造函数A 实例的原型是构造函数B 的实例,也可以认为构造函数A 是构造函数B 的子类。
3. instanceof 对象自己的构造函数、和对象原型的构造函数,以及原型链上的对象的构造函数,都可以成立。
function User() {
}
User.prototype = [100,200];
var u = new User();
console.log(u instanceof User);
console.log(u instanceof Array);
console.log(u instanceof Object);
③ 实现JS 中构造函数和构造函数之间继承
1. 子类中,先把父类调用一遍,并修改其 this 指向。
2. 设置子类的实例的原型是父类的一个实例。
3. 设置子类的实例的constructor 属性 (非必要)
function Person(name, height) {
this.name = name;
this.height = height;
}
Person.prototype.eat = function() {
}
function Man(name, height, aaa) {
Person.call(this, name, height);
this.aaa = aaa;
}
Man.prototype = new Person();
Man.prototype.constructor = Man;
Man.prototype.fun = function() {}
function Girl(name, height, bbb) {
Person.call(this, name, height);
this.bbb = bbb;
}
Girl.prototype = new Person();
Girl.prototype.constructor = Girl;
Girl.prototype.fn = function() {}
2.3 安全的类型检测
function getType(data) {
var str = Object.prototype.toString.call(data)
return str.slice(8, str.length - 1)
}
3 单线程和事件轮询机制
3.1 进程和线程
1. 进程:
进程是CPU 进行资源调度和分配的基本单位。
2. 线程:
线程是CPU进行运算的最小单位,进程的运算也要基于线程。
3. 进程和线程的关系:
- 进程中必须有一个主线程
- 进程中可以同时运行多个线程,这样的程序叫做多线程运行
- 同一个进程的不同线程可以共享数据
- 不同进程之间无法直接共享数据
(类比:
CPU:工厂
进程:车间
线程:工人
)
3.2 JS 单线程运行
为什么 JS 是单线程运行?
如果多线程运行,可能不同线程同时修改DOM, 导致浏览器无法渲染的冲突;最终使用了单线程。
3.3 同步代码和异步代码
1. 同步代码
同步代码也叫同步任务,按照顺序依次执行,上一个任务执行完毕下一个任务开始执行。
2. 异步代码
异步代码也叫异步任务,满足执行条件且执行线程空闲(同步代码执行完毕),执行异步任务。
3. 异步任务:
- 定时器的回调函数
- DOM 事件的回调函数
- Ajax 的回调函数
- promise 的回调函数
4. 注意事项:
- 开启定时器、监听事件本身是同步任务,他的回调函数才是异步任务。
- 异步的代码通常是回调函数,但是回调函数不一定是异步的。
3.4 事件轮询机制
- 执行栈
负责执行代码,不论是同步任务还是异步任务都要进行执行栈执行。
- 管理模块
负责管理异步任务是否满足执行条件,有定时器管理模块、DOM事件管理模块、Ajax 管理模块等
- 回调队列
当管理模块发现异步任务满足条件,将回调函数放入回调队列,等待执行。
队列的特点:先进先出
- 事件轮询
负责监听执行栈什么时候空闲,一旦执行栈空闲,立即将回调队列中的回调函数放入执行栈执行。