JavaScript学习笔记
JavaScript基础复习
数据类型的种类与类型之间的判断
- 基本(值)类型
Number—任意数值—typeof
string—任意字符—typeof
Boolean—true/false—typeof
Undefined—Undefined—typeof
Null—Null—typeof - 对象(引用)类型
Object—typeof/instanceof
Array—instanceof
Function—typeof
数据,变量,内存的理解
- 数据
内存中可读,可传递的保存的特定的‘信息’
一切皆数据,函数也是数据
内存中所有操作的目标:数据 - 变量
程序运行的过程中允许改变的值
一个变量对应一块内存,它的值保存在此内存中 - 内存
一块内存包含两个方面的数据1.内部存储的数据2.地址值的数据 - 内存空间的分类
栈空间:全局变量和局部变量
堆空间:对象 - 内存,数据,变量三者之间的关系
内存是容器,用来存储不同的数据
变量是数据的标识,通过变量我们可以读写内存中的数据
对象的理解和使用
- 什么是对象?
多个数据的集合
用来保存多个数据的容器 - 属性的组成
属性名:字符串(标识)
属性值:任意类型 - 属性的分类
一般:属性值不是function描述对象的状态
方法:属性值为function的属性描述对象的行为 - 特别的对象
数组
函数 - 如何操作内部属性
.属性名
[‘属性名’]
函数的理解和使用
- 什么事函数?
用来实现特定功能的,n条语句封装体
只有函数类型可以执行的,其他都不可以 - 函数的优点
提高复用性
便于阅读交流 - 函数是特殊的对象
instanceof Object===true
函数有属性:prototype
函数的方法:call(),apply()
可以添加新的属性/方法 - 函数的3种调用
一般函数直接调用
构造函数通过new调用
对象:通过.调用内部的属性/方法 - 函数的this
谁调用this就是谁
-匿名函数自调用:
(function(w,obj){})(window,obj)专业术语为IIFE(Immediately Invoked Function Expression)立即调用函数表达式
//Object构造函数模式
var obj = {};
obj.name = 'Tom'
obj.setName = function(name){this.name=name}
//对象的字面量模式
var obj = {
name : 'Tom',
setName : function(name){this.name = name}
}
//构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.setName = function(name){this.name=name;};
}
new Person('tom', 12);
//构造函数加原型组合模式
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.setName = function(name){this.name=name;};
new Person('tom', 12);
原型与原型链
- prototype属性
每个函数都有prototype属性,它默认指向一个Object空对象
原型对象中有个constructor,它指向函数对象 - 显示原型和隐式原型
每个function都有一个prototype,即显示原型(属性)
每个实例对象都有一个__proto__,即隐式原型(属性)
函数的prototype属性:在定义函数自动添加的,默认是一个空Object
对象的__proto__属性:创建是自动添加,默认为构造函数的prototype属性值 - 原型链
- 执行上下文
变量声明提升
通过var定义(声明)的变量,在定义语句之前就可以被访问到,访问到的值为undefined
函数声明提升
通过function声明的函数,在之前就可以直接调用,值为函数定义的对象
全局执行上下文
在执行全局代码时蒋window确定问全局上下文
对全局数据进行预处理
var定义的全局变量==>undefined,添加为window的属性
function生命的全局函数,添加为window的方法
this==>赋值(window)
函数执行上下文
在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟)
对局部数据的处理- 形参变量==>赋值(实参)==>添加为添加为执行上下文的属性
- arguments==>赋值(实参列表), 添加为执行上下文的属性
- var定义的局部变量==>undefined, 添加为执行上下文的属性
- function声明的函数 ==>赋值(fun), 添加为执行上下文的方法
- this==>赋值(调用函数的对象)
在全局代码执行前,js引擎就会创建一个栈来储存管理所有的执行上下文对象
全局执行上下文(window)确定后,将其添加到栈中(压栈)
在函数执行上下文创建后, 将其添加到栈中(压栈)
当前函数执行完后,将栈顶对象移除(出栈)
当所有的代码执行完后, 栈中只剩下window
作用域与作用域链
- 作用域
全局作用域
函数作用域
块作用域(ES6)
作用域链
- 多个上下级关系的作用域形成的链, 它的方向是从下向上的(从内到外)
- 查找变量时就是沿着作用域链来查找的
查找一个变量的规则
- 在当前作用域下的执行上下文中查找对应的属性, 如果有直接返回, 否则进入2
- 在上一级作用域的执行上下文中查找对应的属性, 如果有直接返回, 否则进入3
- 再次执行2的相同操作, 直到全局作用域, 如果还找不到就抛出找不到的异常
闭包
使用chrome调试查看
理解一: 闭包是嵌套的内部函数
理解二: 包含被引用变量(函数)的对象
注意: 闭包存在于嵌套的内部函数中
- 产生闭包的条件
函数嵌套
内部函数引用了外部函数的数据(变量/函数) - 常见的闭包
将函数作为另一个函数的返回值
将函数作为参数传递给另一个函数调用 - 闭包的作用
使用函数内部的变量在函数执行完后,仍存活在内存中(延长了局部变量的生命周期)
让函数外部可以操作(读写)到函数内部的数据(变量/数据) - 闭包的生命周期
产生:在嵌套内部函数定义执行完时就产生了(不是调用时)
死亡:当嵌套的内部函数成为垃圾对象是死亡 - 闭包的应用
定义js模块
具有特定功能的js文件
将所有数据和功能都封装在一个函数内部(私有的)
只向外暴露一个或n个方法的对象或函数
模块使用者,只需要模块暴露的对象调用方法来实现对应的功能 - 闭包的缺点
函数执行完后,函数局部变量没有被释放,占用内存时间会变长
容易造成内存泄露 - 解决方法
能不用闭包就不用
及时释放
线程机制与进程 - 进程
进程的一次执行,它占有一片独有的内存空间
可以通过windows任务管理器查看进程 - 线程
是进程内的一个独立执行单元
是程序执行的一个完整流程
是cpu的最小的调度单元 - 关系
一个进程至少有一个线程(主)
程序是在某个进程中的某个线程执行的
浏览器内核模块组成
主线程
js引擎模块:负责js程序的编译与运行
html,css文档解析模块:负责页面文本的解析
DOM/CSS模块:负责dom/css在内存中的相关处理
布局和渲染模块:负责页面的布局和效果的绘制(内存中的对象)
分线程
定时器模块:负责定时器的管理
DOM事件模块:负责事件的管理
网络请求模块:负责Ajax请求
js线程
- js是单线程执行的(回掉函数也是在主线程)
- H5提出了实现多线程方案:Web Workers
- 只能是主线程更新界面
定时器问题 - 定时器并不是真正完全定时
- 如果在主线程执行了一个长时间的操作,可能导致延时才处理
H5 Web Workers