这是我参与「第四届青训营 」笔记创作活动的的第10天
1. 对象的创建模式
1). Object构造函数模式
var obj = new Object()
obj.name = 'Tom'
obj.setName = function(name){this.name=name}
2). 对象字面量模式
var obj = {
name : 'Tom',
setName : function(name){this.name = name}
}
3). 工厂函数模式
// 工厂函数: 返回一个需要的数据的函数
function Person(name, age) {
return {
name: name,
age: age
}
}
var person1 = Person('kobe', 43);
4). 自定义构造函数模式
function Person(name, age) {
this.name = name
this.age = age
this.setName = function(name){this.name=name}
}
var person1 = new Person('tom', 12)
5). 构造函数+原型的组合模式
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function(name){this.name=name}
var person1 = new Person('tom', 12)
2. 继承模式
1). 原型链继承 : 得到方法
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.showName = function () {
console.log(this.name);
}
// 原型继承: 子类的原型 成为 父类的实例
// Child.prototype = {constructor: Child}
Child.prototype = new Person();
Child.prototype.constructor = Child; // 要手动加上原型的constructor属性
// 定义一个child类
function Child(name, age) {
this.name = name;
this.age = age;
}
var child1 = new Child('xiaoming', 18);
2). 借用构造函数继承 : 得到属性
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){}
function Child(xxx,yyy){
Parent.call(this, xxx) //借用父类型的构造函数
}
var child = new Child('a', 'b') //child.xxx为'a', 但child没有test()
3). 组合继承
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){}
function Child(xxx,yyy){
Parent.call(this, xxx) //借用构造函数 this.Parent(xxx)
}
Child.prototype = new Parent() //得到test()
Child.proptotype.constructor = Child
var child = new Child() //child.xxx为'a', 也有test()
3. 理解
1). 定义一个函数背后做了什么?
创建一个Function的实例对象
给对象添加prototype属性, 其值为object空对象(原型对象)
给原型对象添加constructor属性, 指向当前函数对象
2). new一个对象背后做了些什么?
创建一个新的空对象
给对象设置__proto__, 值为构造函数对象的prototype属性值
通过对象执行构造函数体(给对象添加属性/方法)
1. 线程与进程
1). 进程:
程序的一次执行, 它占有一片独有的内存空间
可以通过windows任务管理器查看进程
2). 线程:
是进程内的一个独立执行单元
是程序执行的一个完整流程
是CPU的最小的调度单元
3). 关系
一个进程至少有一个线程(主)
程序是在某个进程中的某个线程执行的
2. 浏览器内核模块组成
1). 主线程
js引擎模块 : 负责js程序的编译与运行
html,css文档解析模块 : 负责页面文本的解析
DOM/CSS模块 : 负责dom/css在内存中的相关处理
布局和渲染模块 : 负责页面的布局和效果的绘制(内存中的对象)
2). 分线程
定时器模块 : 负责定时器的管理
事件响应模块 : 负责事件的管理
网络请求模块 : 负责Ajax请求
3). js线程
js是单线程执行的(回调函数也是在主线程)
H5提出了实现多线程的方案: Web Workers --->var worker = new Worker('./work.js');
只能是主线程更新界面
3. 定时器问题:
定时器并不真正完全定时
如果在主线程执行了一个长时间的操作, 可能导致延时才处理
4. 事件循环机制
1). 代码分类
初始化执行代码: 包含绑定dom事件监听, 设置定时器, 发送ajax请求的代码
回调执行代码: 处理回调逻辑
2). js引擎执行代码的基本流程:
初始化代码===>回调代码
3). 模型的2个重要组成部分:
事件管理模块
回调队列 (callback queue)
4). 模型的运转流程
执行初始化代码, 将事件回调函数交给对应模块管理
当事件发生时, 管理模块会将回调函数及其数据添加到回调列队中
只有当初始化代码执行完后(可能要一定时间), 才会遍历读取回调队列中的回调函数执行
理解ES
- 全称: ECMAScript
- js语言的规范
- 我们用的js是它的实现
- js的组成
-
ECMAScript(js基础)
-
扩展-->浏览器端
- BOM
- DOM
-
扩展-->服务器端
- Node.js
ES5
- 严格模式
-
运行模式: 正常(混杂)模式与严格模式
-
应用上严格式: 'strict mode';
-
作用:
-
使得Javascript在更严格的条件下运行
-
消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为
-
消除代码运行的一些不安全之处,保证代码运行的安全
-
需要记住的几个变化
- 声明定义变量必须用var
- 禁止自定义的函数中的this关键字指向全局对象
- 创建eval作用域, 更安全
-
- JSON对象
- 作用: 用于在json对象/数组与js对象/数组相互转换
- JSON.stringify(obj/arr) js对象(数组)转换为json对象(数组)
- JSON.parse(json) json对象(数组)转换为js对象(数组)
- Object扩展
-
Object.create(prototype[, descriptors]) : 创建一个新的对象
-
以指定对象为原型创建新的对象
-
指定新的属性, 并对属性进行描述
- value : 指定值
- writable : 标识当前属性值是否是可修改的, 默认为true
- get方法 : 用来得到当前属性值的回调函数
- set方法 : 用来监视当前属性值变化的回调函数
-
-
Object.defineProperties(object, descriptors) : 为指定对象定义扩展多个属性
- Array扩展
- Array.prototype.indexOf(value) : 得到值在数组中的第一个下标
- Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标
- Array.prototype.forEach(function(item, index){}) : 遍历数组
- Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组
- Array.prototype.filter(function(item, index){}) : 遍历过滤出一个子数组
- Function扩展
-
Function.prototype.bind(obj)
- 将函数内的this绑定为obj, 并将函数返回
-
面试题: 区别bind()与call()和apply()?
- fn.bind(obj) : 指定函数中的this, 并返回函数
- fn.call(obj) : 指定函数中的this,并调用函数
- Date扩展
- Date.now() : 得到当前时间值
ES6
- 2个新的关键字
- let/const
- 块作用域
- 没有变量提升(不准确)
- 不能重复定义
- 值不可变
-
let
-
作用:同var一样用来声明变量
-
变量提升:
-
全局变量提升
- 会创建一个变量对象(script)用来收集全局作用域下let定义的变量,但是没有赋值
-
局部变量提升
- 会将var let定义的变量全部放到当前函数的变量对象中
-
同var的变量提升的区别
- let提升的变量在未赋值之前不允许被使用
-
-
-
const
- 作用:定有常量
- 特点:定义的常量不可以被修改
-
变量的解构赋值
- 将包含多个数据的对象(数组)一次赋值给多个变量
- 数据源: 对象/数组
- 目标: {a, b}/[a, b]
-
各种数据类型的扩展
-
字符串
-
模板字符串
- 作用: 简化字符串的拼接
- 模板字符串必须用``
- 变化的部分使用${xxx}定义
-
contains(str) : 判断是否包含指定的字符串
-
startsWith(str) : 判断是否以指定字符串开头
-
endsWith(str) : 判断是否以指定字符串结尾
-
repeat(count) : 重复指定次数
-
-
对象
-
简化的对象写法
let name = 'Tom'; let age = 12; let person = { name, age, setName (name) { this.name = name; } }; -
Object.assign(target, source1, source2..) : 将源对象的属性复制到目标对象上
-
Object.is(v1, v2) : 判断2个数据是否完全相等
-
proto属性 : 隐式原型属性
-
-
数组
- Array.from(v) : 将伪数组对象或可遍历对象转换为真数组
- Array.of(v1, v2, v3) : 将一系列值转换成数组
- find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
- findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标
-
函数
-
箭头函数
-
用来定义匿名函数
-
基本语法:
- 没有参数: () => console.log('xxxx')
- 一个参数: i => i+2
- 大于一个参数: (i,j) => i+j
- 函数体不用大括号: 默认返回结果
- 函数体如果有多个语句, 需要用{}包围
-
使用场景: 多用来定义回调函数
-
特点:
- this:箭头函数没有自己的this,不是调用的时候决定的,而是定义的时候决定的
- 理解: - 看定义的时候外部是否有函数,如果有当前箭头函数的this同外部函数的this指向是同一个对象 - 如果没有,箭头函数this指向的是window
- 箭头函数不能用作构造函数
-
-
形参的默认值
- 定义形参时指定其默认的值
-
三点运算符
-
rest(可变)参数
- 通过形参左侧的...来表达, 取代arguments的使用
- 它比arguments更加灵活
- 同样是来收集函数的实参列表
- 使用三点运算符收集的是一个真数组
- 可以根据需求收集指定的参数
-
扩展运算符(拆包)
- 语法:...arr
- 作用:可以分解出数组中的数据
- 原理:三点运算符会调用iterator接口,如果底层有这个接口,那就可以去遍历数组
-
-
-
Symbol
- 理解:ES6提供的一种新的数据类型
- 基本数据类型:string, number, boolean, undefined, null, symbol,
- typeof返回值:number, string, boolean, undefined, object, function, symbol
- symbol特点:值是唯一的
-
iterator遍历器对象
function iteratorUtil() { // iterator接口 : 方法 || api console.log('我的方法被调用了', this); // this是遍历的目标数组或目标对象 // console.log(target);// undefined // 缓存this let that = this; let index = 0; // 标识指针的起始位置 let keys = Object.keys(that);// 获取对象中所有key的数组 if(this instanceof Array){ // 遍历数组 return { // 生成iterator遍历器对象 next: function (){ // 可以使用箭头函数解决this的指向问题 return index < that.length ? {value: that[index++], done: false} : {value: that[index++], done: true} } } }else {// 遍历对象 return { // 生成iterator遍历器对象 next: function (){ // 可以使用箭头函数解决this的指向问题 return index < keys.length?{value: that[keys[index++]], done: false}:{value: that[keys[index++]], done: true} } } } } Array.prototype[Symbol.iterator] = iteratorUtil; Object.prototype[Symbol.iterator] = iteratorUtil; -
set/Map容器结构
-
容器: 能保存多个数据的对象, 同时必须具备操作内部数据的方法
-
任意对象都可以作为容器使用, 但有的对象不太适合作为容器使用(如函数)
-
Set的特点: 保存多个value, value是不重复 ====>数组元素去重
-
Map的特点: 保存多个key--value, key是不重复, value是可以重复的
-
API
- Set()/Set(arr) //arr是一维数组
- add(value)
- delete(value)
- clear();
- has(value)
- size
- Map()/Map(arr) //arr是二维数组
- set(key, value)
- get(key)
- clear()
- has(key)
- size
- for--of循环
- 可以遍历任何容器
- 数组
- 伪/类数组
- 字符串
- 可迭代的对象
- Promise
-
解决
回调地狱(回调函数的层层嵌套, 编码是不断向右扩展, 阅读性很差) -
能以同步编码的方式实现异步调用
-
在es6之前原生的js中是没这种实现的, 一些第三方框架(jQuery)实现了promise
-
ES6中定义实现API:
// 1. 创建promise对象 var promise = new Promise(function(resolve, reject){ // 做异步的操作 if(成功) { // 调用成功的回调 resolve(result); } else { // 调用失败的回调 reject(errorMsg); } }) // 2. 调用promise对象的then() promise.then(function( result => console.log(result), errorMsg => alert(errorMsg) ))
- class类
- 用 class 定义一类
- 用 constructor() 定义构造方法(相当于构造函数)
- 一般方法: xxx () {}
- 用extends来定义子类
- 用super()来继承父类的构造方法
- 子类方法自定义: 将从父类中继承来的方法重新实现一遍
- js中没有方法重载(方法名相同, 但参数不同)的语法
- 模块化(后面讲)
ES7
-
指数运算符: **
-
Array.prototype.includes(value) : 判断数组中是否包含指定value
-
区别方法的2种称谓
-
静态(工具)方法
- Fun.xxx = function(){}
-
实例方法
- 所有实例对象 : Fun.prototype.xxx = function(){} //xxx针对Fun的所有实例对象
- 某个实例对象 : fun.xxx = function(){} //xxx只是针对fun对象
-