一、名词解释
思考:什么是对象、类、实例?
- 一切皆对象,在众多的对象当中我们会发现一些对象,它们具有相同的特征
- 此时就可以做抽象,最终产出类
- 实例就是我们
new之后的一个产物(对象--->类--->实例) 思考:什么是普通函数,什么是构造函数?首先通过一段代码说明:
function Foo (m, n) {
let ret = m + n
this.m = m
this.n = n
return ret
}
// 01 普通函数调用
// let ret = Foo(10, 20)
// console.log(ret) // 30
// 02 构造函数执行
let res = new Foo(20, 20)
console.log(res) // {m: 20, n: 20}
图解代码执行过程:
分析:
new操作到底做了什么?
当执行 new 操作的时候浏览器会自动开辟一个内存空间,用于存放实例对象。然后与 this 进行关联。简述:创建对象--关联this--返回对象
返回对象的规则:
- 构造函数中无
return时,默认返回this - 构造函数中有
return时,若为基本数据类型忽略它,返回this,若为引用类型,返回当前引用对象的值
二、面向对象(非Class)
1. prototype 属性
- 每个函数(除箭头)数据类型,都自带一个
prototype属性,指向原型对象(Function除外) - 每一个原型对象都自带一个
constructor属性,指向当前构造函数本身 - 函数类数据类型:普通函数、箭头函数、生成器函数、构造函数(自定义类)、内置函数(内置构造函数)
2. __proto__属性
- 每个对象数据类型,都自带一个
__proto__属性,指向当前实例所属类的原型对象(prototype) - 对象数据类型:普通对象、数组对象、正则、
prototype原型对象、实例对象、函数也是对象
3. Object类
- 所有对象如果不知道是new谁来的,那么它就是
Object的一个实例 Object本身也是一个函数,因此同样具有prototype属性,指向它自己的原型对象Object的原型对象本身也是一个对象,因此它身上也具有一个__proto__属性,内部设计它指向null以一个实例分析以上的概念:
function Foo() {
this.m = 10
this.n = 24
this.getM = function () {
console.log(this.m)
}
}
Foo.prototype.getM = function () {
console.log(this.m)
}
Foo.prototype.getN = function () {
console.log(this.n)
}
let foo1 = new Foo
let foo2 = new Foo
图解以上代码中原型和原型链的查找:
Foo.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true
Foo.prototype.constructor === Foo // true
Object.prototype.constructor === Object // true
实例属性的查找规则:
- 首先会找自己的私有属性,如果有则直接使用
- 若私有属性中不存在,则默认会基于
__proto__属性找到实例所属类的原型对象 - 若原型对象上也没有,则继续基于原型对象的
__proto__往上接着找,直到找到Object.prototype为止
三、Function 与 Object
1、函数有哪些?
- 普通函数调用(堆栈作用域及作用域链)
- 构造函数(原型及原型链)
- 对象(键值对)[所谓的高阶应用] 把函数当作参数或返回值进行使用 上述函数的三种角色之间并没有必然的联系,但是函数是一等公民(默认函数就是函数,除非考虑函数的高阶应用可以把它看作对象更好理解和使用)
2、重点语录
Function是一等公民,虽然有很多种身份,但最重要的还是函数- 每个对象都存在
__proto__属性,指向所属类的原型对象 - 每个函数存在
prototype属性(有例外),指向它的原型对象【有的函数没有原型对象】 - 所有对象如果不知道谁是爹,那么就都安在
Object身上 ,且Object本身也是一个函数 Function与Object是JS当中二大并行的基类,虽然最终查找的落脚点都是Object- 所有的函数都是
new Function来的 Function.prototype是一个匿名函数,但是它的处理机制和其它的原型对象是一样的(指向Object.prototype), 即:Function.prototype.__proto__ === Object.prototype
3、实例演示
function Foo() {}
let foo = new Foo
图解Function与Object的关联:
4、函数的prototype属性
若失去prototype属性,则不能执行new操作。
哪些函数不具备prototype属性?(即内部内部没有this)
- 箭头函数
Function.prototype- 对象中的函数简写
// 对象中的函数简写
const obj = {
foo() {
// 这个函数也没有prototype
}
}
new obj.foo()
四、this
1. this是什么?
this是当前函数的执行主体(谁执行了这个函数),不等同于执行上下文,也不等同于作用域
通俗理解:小明在教室讲课。
- 其中讲课是一个动作(函数)
- 教室提供了黑板,讲台等等(执行上下文)
- 小明就是主体,本次函数在当前执行上下文里的
this指向
2. 常出现this的场景
- 事件绑定(oBtn.onclick = function() { this // 指当前
DOM对象oBtn}) - 普通函数调用
- 构造函数(
this一般指向new Foo的实例对象) - 箭头函数(不具备
this) - 基于
call/bind/apply强制改变this的指向(obj.foo.call(obj2) //this指向obj2)
3. this指向规律
- 函数执行的时候需要查看函数的前端是否有. 如果有,则点前面的对象就执行主体
this,如果没有. 一般就是window或undefined(严格模式) - 特殊情况
- 匿名函数中的
this是window或者undefined
(function () {
console.log(this) // window
})()
- 回调函数中的
this是window或者undefined
let arr = [1]
obj = { name: '小明' }
arr.map(function(item, index) {
console.log(this) // { name: '小明' }
}, obj) // obj修改了this指向
- 小括号括号语法
let obj = {
fn: function() {
console.log(this, 111)
}
}
let fn = obj.fn
fn() // 没. this指向window
obj.fn() // 有. this指向obj
(obj.fn)() // 如果小括号里只有一项,那么和没写小括号是一样的
(10, 20 ,30) // 30
// 如果小括号里有多项,那么它会返回最后一项
// 且有一个现象,它相当于是对最后一项做了一次拷贝
// 即:把一个数据从一个地址挪到另一个地方保存,和obj没关系了
// 下面的代码就好像是在执行 fn() ---> window
(10, fn, obj.fn)() // window{...} 111
4. this实战
var a = 3,
obj = { a: 5 }
obj.fn = (function () {
this.a *= ++a
return function (b) {
this.a *= (++a) + b
console.log(a)
}
})();
var fn = obj.fn
obj.fn(6)
fn(4)
console.log(obj.a, a)
图解代码的执行过程:
五、JS 异步编程
六、EventLoop 模型
七、执行顺序题目练习
1、经典题目
setTimeout(() => {
console.log('1')
}, 30)
console.log(2)
setTimeout(() => {
console.log(3)
}, 20)
console.log(4)
console.time('AA')
// 消耗95ms
for (let i = 0; i < 88888888; i++) { }
console.timeEnd('AA')
console.log(5)
setTimeout(() => {
console.log(6)
}, 18)
console.log(7)
setTimeout(() => {
console.log(8)
}, 25)
console.log(9)
2、主线程占用
// 死循环是将主线程彻底占用,其它所有事情不在处理
// 跑出异常只会影响下面的同步任务,已经放置在队列当中的任务会继续执行
setTimeout(() => {
console.log(1)
}, 0)
console.log(2)
while (true) { }
// throw new Error('手动抛出异常')
// console.log(a)
console.log(3)
setTimeout(() => {
console.log(4)
}, 10)
console.log(5)
八、Promise
九、async 与 await
十、练习
var a = [];
for(var i = 0; i < 10; i++) {
a[i] = function() {
console.log(i)
}
}
a[6]()
var a = 10;
var obj = {
a: 20,
fn() {
setTimeout(() => {
console.log(this.a)
})
}
}
obj.fn()