文章目录
前言
本周做了五子棋项目,对之前的学习进行实操
一、函数执行
函数创建
函数的作用域关系在函数创建时就已经执行
函数执行
-预编译/预处理
-初始化作用域(链)
-初始化this(箭头函数没有此操作)
-初始化arguments(箭头函数没有此操作)
-变量提升
变量提升:声明(var)
函数提升:整体
-执行代码
执行上下文:存放此次函数相关的一系列内容的一个对象
执行栈:存放执行上下文
当函数开始执行时,函数生成一个对应的私有执行上下文,放入执行栈中;当函数执行结束时,此执行上下文会被移出执行栈,并被销毁
执行栈(ECS)的空间有限,如果内容的执行栈数量超过其容纳限度,将会出现爆栈(错误)
执行上下文(EC:execute context)
-函数执行上下文EC(sum)
-全局执行上下文EC(G)
执行上下中组成(ES3)
-变量对象:用于存储当前函数定义的变量
-作用域(词法作用域):获取变量->词法环境
-this(最新的语法标准中,this位于变量环境)
this 指向问题:
- 默认指向:window (严格模式:undefined)
- 隐式指向:当函数有调用者时,执行调用函数的对象
- 显示(强制)指向:
- call,apply: 更改 this 指向,立即执行函数 (call,apply 的区别在于传递参数的方式不一样)
- bind : 更改 this 指向, 返回一个绑定了指向的新函数
- 箭头函数:自身没有 this, 从父级中获取 (无法修改)
- 事件绑定:绑定事件的元素
- new 绑定: 指向创建出来的对象
二、闭包
定义
官方定义:
一个函数和对其周围状态(Lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包圈),这样的组合就是闭包(closure)
通俗定义:
当函数嵌套函数,其内部函数使用了外部函数的变量
产生原因
解决内部函数需要在需要使用外面函数的变量时,不能因为外部函数由于执行结束,执行上下文被销毁而无法供内部函数使用
闭包函数:内部函数
闭包对象:存储内部函数使用的外部函数的变量的对象
闭包缺点:
-耗内存:由于内部函数一直存在,所以对应的闭包对象会一直存在直到内部函数被回收
内存泄漏:部分内存长久被占用着,无法被释放掉(例如定时器,闭包未清除)
闭包优点:
-让局部变量生命周期更长
-可以让变量不易被其他内容修改
三、面向对象编程
1.对象
定义:key-value结构,用于存储属性和方法的数据集合
创建对象:
-原生
-构造函数 let obj = new Object()
-字面量/直接量:let obj ={}
-自定义构造函数
构造函数(类):
-本质就是一个普通函数,只不过调用方式和使用目的不同
-调用方式:使用new关键字
-使用目的:生成具有特定功能属性的对象
通过构造函数创建的对象称为实例对象
如果在不使用new关键字的情况下,调用构造函数,会发生什么?
-首先,返回值将不是一个对象,而是undefined
-而且会在window中生成原本应该属性对象中的属性,污染全局环境
-可以使用new.target判断是否用过new关键字进行调用,解决非new调用
补充:如果没有new一个对象,可以编写“抛出错误”
或者直接给它强制添加上new
2.new关键字
1.生成一个空对象
2.将this指向生成的对象
3.当代码执行结束,如果函数没有返回对象,将返回this,如果返回了对象,则返回定义的该值
3.原型(原型对象)
->解决函数的重复创建
-在每个构造函数上,都存在一个属性prototype,其指向一个空对象,即原型对象,当前构造函数所创建的实例对象,都可以访问到这个原型对象
-将公共方法放置在原型对象,解决了方法的重复创建
原型链:
-当在实例对象访问一个属性方法时,如果自身没有,会在其对应的原型对象上去寻找;如果原型上也没有,由于原型对象也是由另一个构造函数(默认为Object)所创建,所以原型对象又能访问其自身对应的原型对象,依次向上查询,直到Object构造函数的原型对象上没有位置
原型对象
实例对象间互相访问:
-构造函数->原型:prototype
-原型->构造函数:constructor
-实例对象->原型:proto
-实例对象->构造函数:实例对象->原型->构造函数
-原型->实例对象:不能
-构造函数->实例对象:不能
对象方法
复制对象 Object.assign(target,…sources); ->浅拷贝
创建对象 Object.create(property) *
属性描述符(属性)–了解
● configurable:可配置性/删除
● enumerable:可枚举性/可遍历性
● value:属性值
● writable:可写性
● getter&setter:属性拦截器(只能拦截属性)
● proxy:对象代理(直接把整个对象的所有属性都可以监听到,拦截所有对象,性能也更高)
对象遍历
● for in 注意:会将原型上的属性和方法一并遍历出来
● Object.keys() 遍历属性名,返回数组,不包含不可枚举属性
● Object.values() 遍历属性值,返回数组,不包含不可枚举属性
● Object.entries() 遍历属性值,返回包含属性名和属性值的二维数组,不包含不可枚举属性
● Object.getOwnPropertyNames() 获取对象的所有属性名,包含不可枚举属性
● Object.getOwnPropertySymbols() 获取对象的所有symbols属性
原型控制
● Object.getPrototypeOf()
● Object.setPrototypeOf()
4.深浅拷贝
对象拷贝:通过遍历对象属性,将当前对象中的属性复制到新对象中
浅拷贝:在进行对象拷贝时,不区分数据是否是对象类型;如果拷贝对象内部嵌套对象,则拷贝后的对象和原有对象会出现关联,内部对象出现变量,拷贝对象和新对象同步更改
深拷贝:在进行对象拷贝时,区分数据类型,如果是对象类型,则需要单独进行拷贝一份,以保证拷贝对象和新对象毫无关联,相互独立
实现方式:
浅拷贝:
● Object.assign
● 扩展运算符
● 遍历
深拷贝
● JSON
JSON: javascript object nation -> 文本格式(字符串)
Object -> JSON: JSON.stringify()
JSON -> Object: JSON.parse()
JSON缺陷只能转换一些常用的属性,不能转换函数类型
● 遍历
○ 拷贝的数据类型,原来是什么类型,就应该生成对应的数据类型
○ 判断拷贝内容是否是对象,不是对象直接返回
○ 处理循环引用
编程范式:
面向过程编程
面向对象编程
函数式编程
5.面向对象编程
面向对象编程特性
● 封装
● 继承
● 多态
○ 重写
○ 重载
面向过程
优点:逻辑简单;性能好
缺点:可读性;可维护性;可复用性;可扩展性
面向对象
优点:可读性;可维护性;可复用性;可扩展性
缺点:逻辑比较复杂;性能开销大
对象封装
● 原始模式
● 工厂模式
● 构造函数
● 原型模式
● 组合模式:构造函数+原型
● class语法:组合模式的语法糖(限制非new的调用)
静态属性、方法
static开头命名
私有属性以#开头命名,只能在class语法中使用
6.对象继承
● 原型链继承:将子类的原型设置为父类的实例对象,扩展原型链
○ 缺点:会在子类的原型上添加无用的空属性(所以产生原型式继承)
○ 最好还是重新指正一下constructor
● 原型式继承
● 借用构造函数继承
● 组成继承:原型链+借用构造函数
● 寄生组合继承:原型式 + 借用构造函数
● class 继承
此处的super等效于,子类属性必须写在super之后
7.解构
(一般运用于参数很多的情况)
对象解构
数组解构,按照位置来解构
a.
b.arr1=3,4,5
实际情况运用
如果没有传参,可以用以下写法
总结
乱七八糟的,将就着看吧