JavaScript

数据类型

1.分类
基本(值)类型

String :任意字符串

Number :任意的数字

bollean :true/false

undefined :undefined

null :null

对象(引用)类型

Object :任意对象

Function :一种特别的对象(可以执行)

Array :一种特别的对象(数值下标,内部数据是有序的)

2.判断

typeof :返回数据类型的字符串表达 (可以判断:undefined/数值/字符串/布尔值)(不能判断 :null/object object与array)

instanceof (实例):判断对象的具体类型 (对象 instanceof 具体类型)

=== :可以判断undefined/null

显式原型和隐式原型

1.每个函数function 都有一个prototype, 即显式原型(属性),默认指向 一个空的object对象

  1. 每个实例对象都有一个__ proto__ ,可称为隐式原型(属性)

  2. 对象的隐式原型的值为其对应构造函数的显式原型的值

  3. 内存结构(图)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OSIa9HaH-1627116076777)(C:\Users\庸人\AppData\Roaming\Typora\typora-user-images\1619692928131.png)]

  1. 总结:
    *函数的prototype属性: 在定义函数时自动添加的,默认值是一 个空0bject对象
    *对象的____proto__ 属性: 创建对象时自动添加的,默认值为构造函数的prototype属性值
    *程序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前)

function Fn() { //内部语句:this.prototype={}
// 1. 每个函数function都有一个prototype, 即显式原型属性,默认指向一个空的bject对象
console. 1og(Fn. prototype)
// 2.每个实例对象都有一个_ proto__ ,可称为隐式原型 var fn = new Fn() //内部语句: this._ .proto__ = Fn.prototypel console.1og(fn._ proto_ )
// 3.对象的隐式原型的值为其对应构造函数的显式原型的值
console.1og(Fn. prototype===fn._ proto_ ) // true

原型链

1.原型链(图解)
访问一个对象的属性时,先在自身属性中查找,找到返回
如果没有再沿者_ proto_ 这条链向上查找, 找到返回
如果最终没找到,返@undefined
别名:隐式原型链
*作用:查找对象的属性(方法)
2.构造函数/原型/实体对象的关系(图解)
3.构造函数/原型/实体对象的关系2(图解)

变量提升和函数提升

1.变量声明提升
通过var定义(声明)的变量,在定义语句之前就可以访问到
*值: undefined
2.函数声明提升
*通过function声明的函数,在之 前就可以直接调用
*值:函数定义(对象)

function fun(){} 是

var fun=function (){} 不是,它是变量声明

3.问题:变量提升和函数提升是如何产生的

函数提升比变量提升优先级高,若同名,则函数名会覆盖变量名

执行上下文

1.代码分类(位置)
全局代码
*函数(局部)代码
2.全局执行上下文
*在执行全局代码前将window确定为全局执行上下文
*对全局数据进行预处理

  • var定义的全局变量==>undefined, 添加为window的属性

  • function声明的全局函数==>賦值(fun),添加为window的方法

  • this==> 赋值(window)
    *开始执行全局代码

    3.函数执行上下文
    *在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
    *
    对局部数据进行预处理
    *形渗变量==>赋值(实参)==>添加为执行上下文的属性

  • arguments==>赋值(实参列表),添加为执行上下文的属性

  • var定义的局部变量==>undefined, 添加为执行上下文的属性

  • function声明的函数==>赋值(fun),添加为执行上下文的方法:

  • this==>赋值(调用函数的对象)
    *开始执行函数体代码

  • 原则:N+1

执行上下文栈

1.在全局代码执行前,JS引擎就会创建一个栈来存储管理所有的执行上下文对象
2. 在全局执行上下文(window)确定后, 将其添加到栈中(压栈)
3. 在函数执行上下文创建后,将其添加到栈中(压栈)
4. 在当前函数执行完后,将栈顶的对象移除(出栈)
5. 当所有的代码执行完后, 栈中只剩下window

测试题2:
/
if (!(b in window)) {
varb=1
}
console.1og(b) // undefined
/

测试题3:
*/
varC=1
function c© {
|console.1og©
c(2) // 报错,c为变量1,不是一个函数

作用域

1.理解
*就是一块”地盘", 一个代码段所在的区域
*它是静态的(相对于上下文对象),在编写代码时就确定了
2.分类
*全局作用域
*函数作用域
*没有块作用域(ES6有了)
3.作用
*隔离变量,不同作用域下同名变量不会有冲突

作用域与执行上下文

1.区别
*全局作用城之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时
*全局执行上下文环境是在全局作用域确定之后,js代码马上执行之前创建
*函数执行上下文是在调用函数时,函数体代码执行之前创建
2.区别2
。*作用城是静态的, 只要函数定义好了就一-直存在, 且不会再变化
*执行上下文是动态的, 调用函数时创建, 函数调用结束时就会自动释放
3.联系
*执行上下文环境(对象)是从属于所在的作用域
*全局上下文环境==>全局作用域
“ 函数上下文环境==>对应的函数使用域

作用域链

1.理解
多个上下级关系的作用域形成的链,它的方向是从 下向上的(从内到外)
*查找变量时就是沿着作用域链来查找的
2.查找一个变量的查找规则
*在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
在上一级作用域的执行上下文中查找对应的属性,如果有直接返回, 否则进入3
*再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常

var X=10;
function fn() {
console.1og(风);
}
function show(f) {
var X=20;
f();
}
show(fn);  // 10,作用域
var fn = function () {
console.1og(fn)
fn()  //输出function函数
var obj={
fn2: function () {
consple.1og(fn2)  //报错,先在局部作用域中找,没找到,再到全局中找,也没找到,只有obj.fn2

//console. Log(this . fn2)  正确
}
}
obj. fn2()

闭包

for (var i = 0, Length=btns . length; i < Length; i++) {
var obj = btns[i]
}//这样写,length只计算了一次

1…如何产生闭包?
*当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
2.闭包到底是什么?
*使用chrome调试查看
*理解一:闭包是嵌套的内部函数(绝大部分人
*理解二:包含被引用变量(函数)的对象(极少数人)
*注意:闭包存在于嵌套的内部函数中
3.产生闭包的条件?
*函数嵌套
*内部函数引用J外部函数的数据(变量/函数)

闭包个数=外部函数调用的次数

3.作用

  1. 使用函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)
  2. 让函数外部可以操作(读写到函数内部的数据(变量/函数)

问题:
1.函数执行完后,函数内部声明的局部变量是否还存在?一般是不存在, 存在于闭中的变量才可能存在
2.在函数外部能直接访问函数内部的局部变量吗?不能,但我们可以通过闭包让外部操作它

1.产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
2.死亡:在嵌套的内部函数成为垃圾对象时

闭包的缺点和解决

1.缺点
*
函数执行完后,函数内的局部变量没有释放, 占用内 存时间会变长
*
容易造成内存泄露
2.解决
能不用闭包就不用
及时释放

内存溢出和内存泄漏

1.内存溢出

一种程序运行出现的错误
*当程序运行需要的内存超过了剩余的内存时,就出抛出内存溢出的错误
2.内存泄露
*占用的内存没有及时释放
*内存泄露积累多了就容易导致内存溢出
*常见的内存泄露:
*意外的全局变量
没有及时清理的计时器或回调函数
*闭包

//代码片段一
var name = "The Window" ; .
var object = {
name : "My object",
getNameFunc : function(){
return function(){
return this . name;
};
}
};
alert(object . getNameFunc()()); //  the window
//object . getNameFunc()的()this指window
//代码片段二
var name2 = "The Window";
var object2 = {
name2 : "My 0bject" ,
getNameFunc : function(){
var that = this;
return function(){
return that . name2;
}
};
};
alert(object2.getNameFunc()()); // My Object
//that是getNameFunc()的调用者,为object
//例题 
function fun(n,o) {
    console.log(o)
    return {
    fun : function(m){
    return fun(m, n);
}
}
}
    var a = fun(0); a.fun(1); a.fun(2); a.fun(3);//undefined,?,?,? 0 0 0
    var b = fun(0) . fun(1) . fun(2). fun(3);//undefined,?,?,? 0 1 2
    var c = fun(0).fun(1); c.fun(2); c.fun(3);//undefined,?,?,? 0 1 1

对象创建模式

方式一: object 构造函数模式
*套路:先创建空0bject对象, 再动态添加属性1方法
*适用场景:起始时不确定对象内部数据
问题:语句太多

方式二:对象字面量模式
*套路:使用{}创建对象, 同时指定属性/方法
*适用场景:起始时对象内部数据是确定的
*问题:如果创建多个对象,有重复代码

方式三:工厂模式
*套路:通过工厂函数动态创建对象并返回
*适用场景:需要创建多个对象
*问题:对象没有一个具体的类型,都是0bject类型

方式四:自定义构造函数模式
*套路:自定义构造函数,通过new创建对象
*适用场景:需要创建多个类型确定的对象
*问题:每个对象都有相同的数据,浪费内存

方式六:构造函数+原型的组合模式
*套路:自定义构造函数,属性在函数中初始化,方法添加到原型上
*适用场景:需要创建多个类型确定的对象

原型链继承

1.套路
1.定义父类型构造函数
2.给父类型的原型添加方法
3.定义子类型的构造函数
4.创建父类型的对象赋值给子类型的原型
5.将子类型原型的构造属性设置为子类型
6.给子类型原型添加方法
7.创建子类型的对象:可以调用父类型的方法
2.关键
1.子类型的原型为父类型的一个实例对象

借用构造函数继承

方式:借用构造函数继承(假的)
1.套路:
1.定义父类型构造函数
2.定义子类型构造函数
3.在子类型构造函数中调用父类型构造
2.关键:
1.在子类型构造函数中通用super()调用父类型构造函数

组合继承

方式:原型链+ 借用构造函数的组合继承
1.利用原型链实现对父类型对象的方法继承
2.利用super() 借用父类型构建函数初始化相同属性

代码如下:

function Person(name, age) {
  this.name = name
  this.age = age
}
  Person.prototype.setName = function (name) {
    this.name = name
  }
function Student(name, age, price) {
  Person.call(this, name, age) // 相当于: this.Person(name, age)
  /*this.name = name
  this.age = age*/
  this.price = price
}
Student . prototype = new Person() //I 为了能看到父类型的方法
Student. prototype. constructor = Student

Student.prototype.setPrice = function (price) {
          this.price = price
        }

进程与线程

浏览器内核

支撑浏览器运行的最核心的程序(核心代码)
不同的浏览器可能不一样
内核由很多模块组成:

js引擎模块:负责js程序的编译与运行
2.html,css文档解析模块:负责页面文本的解析
3.DOM/CSS模块:负责dom/css在内存中的相关处理
4.布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)
…等等
5.定时器模块:负责定时器的管理)
6.事件响应模块:负责事件的管理分 线程
7.网络请求模块:负责ajax请求

定时器

1.定时器真是定时执行的吗?
*定时器并不能保证真正定时执行
一 般会延迟一J点(可以接受), 也有可能延迟很长时间(不能按受)
2.定时器回调函数是在分线程执行的吗?
*在主线程执行的,js是单线程的
3.定时器是如何实现的?
*事件循环模型

JS是单线程执行的

1.如何证明js执行是单线程的?

setTimeout()的回调函数是在主线程执行的
*定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行
2.为什么js要用单线程模式,而不用多线程模式?
JavaScript的单线程,与 它的用途有关。
*作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
*这决定了它只能是单线程, 否则会带来很复杂的同步问题
3.代码的分类:
*初始化代码
*回调代码

  1. js引擎执行代码的基本流程
    *先执行初始化代码:包含- 一些特别的代码 回调函数(异步执行 )

  2. *设置定时器
    *绑定监听
    *发送ajax请求
    *后面在某个时刻才会执行回调代码

事件的循环模型

1.所有代码分类
*初始化执行代码(同步代码):包含绑定dom 事件监听,设置定时器, 发送ajax请求的代码
*回调执行代码(异步代码):处理回调逻辑

  1. js引擎执行代码的基本流程:*初始化代码===>回调代码

  2. 模型的2个重要组成部分:

*事件管理模块
*回调队列
  1. 模型的运转流程
*执行初始化代码,将事件回调函数交给对应模块管理
*当事件发生时,管理模块会将回调函数及其数据添加到回调列队中
*只有当初始化代码执行完后(可能要一 定时间), 才会遍历读取回调队列中的回调函数执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BqwiW0Tj-1627116076781)(C:\Users\庸人\AppData\Roaming\Typora\typora-user-images\image-20210502094117793.png)]

H5 web workers多线程

事件循环模型

JS是单线程执行的

1.如何证明js执行是单线程的?

setTimeout()的回调函数是在主线程执行的
*定时器回调函数只有在运行栈中的代码全部执行完后才有可能执行
2.为什么js要用单线程模式,而不用多线程模式?
JavaScript的单线程,与 它的用途有关。
*作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。
*这决定了它只能是单线程, 否则会带来很复杂的同步问题
3.代码的分类:
*初始化代码
*回调代码

  1. js引擎执行代码的基本流程
    *先执行初始化代码:包含- 一些特别的代码 回调函数(异步执行 )

  2. *设置定时器
    *绑定监听
    *发送ajax请求
    *后面在某个时刻才会执行回调代码

事件的循环模型

1.所有代码分类
*初始化执行代码(同步代码):包含绑定dom 事件监听,设置定时器, 发送ajax请求的代码
*回调执行代码(异步代码):处理回调逻辑

  1. js引擎执行代码的基本流程:*初始化代码===>回调代码

  2. 模型的2个重要组成部分:

*事件管理模块
*回调队列
  1. 模型的运转流程
*执行初始化代码,将事件回调函数交给对应模块管理
*当事件发生时,管理模块会将回调函数及其数据添加到回调列队中
*只有当初始化代码执行完后(可能要一 定时间), 才会遍历读取回调队列中的回调函数执行

[外链图片转存中...(img-BqwiW0Tj-1627116076781)]

H5 web workers多线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值