前端JS进阶回顾2
面向对象
每一个对象具备明确分工,具备封装性、继承性、多态性
面向对象-构造函数
面向对象编程借助于构造函数实现
在进阶1中提到的构造函数在实例化新对象时会重新开辟空间存储新值,存在浪费内存的问题
原型
原型能够解决构造函数中浪费内存的问题
构造函数中通过原型分配的函数是所有对象所共享的
JS规定:每一个构造函数都有一个prototype属性,指向原型对象(每个构造方法只有一个),该对象可以挂载函数,因此可以将公共的方法定义在原型对象上,其中无论是构造函数还是原型对象中,this都指向实例化的对象
1 | |
constructor属性
原型对象内都存在constructor属性(构造器-构造函数),该属性指向构造函数
在对原型对象进行赋值多个方法时,会使用对象赋值的形式,但会覆盖构造函数原型对象原有的内容,使修改后的原型对象constructor不在指向原有构造函数,为解决该问题:
1 | |
对象原型
每个构造函数都有一个原型对象,而构造函数能够创建实例对象,实例对象依靠对象原型访问原型对象内的属性
**对象原型__proto__**是对象的一个属性(只读),指向构造函数的原型对象,有些浏览器是[[prototype]]
1 | |
原型继承
1 | |
上述就是一个继承,但存在问题,当多个构造函数继承同一个对象时,会存在变量污染,此时可以使用继承构造函数的实例化对象解决
1 | |
原型链
原型对象中也有对象原型,其中原型对象的对象原型指向Object的原型对象(构造函数的原型对象,所有对象包括原型对象都是由Object构造的),Object的原型对象的对象原型为null
原型链是基于原型对象的继承使得不同的构造函数的原型对象关联起来的链状结构
原型链为对象的属性或方法提供了一条查找链
instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
深浅拷贝
运用于复制对象,在直接复制对象时,修改新对象属性时会污染原对象属性
浅拷贝
浅拷贝拷贝的是简单数据的值
1 | |
assgin()
1 | |
深拷贝
浅拷贝只拷贝简单数据类型的值,当对象内存在对象(复杂数据),栈内存储的数据地址指向堆内数据,浅拷贝依旧存储堆内复杂数据的地址,导致依旧指向原堆内数据,造成污染。
深拷贝能解决这个问题
递归函数
1 | |
lodash-cloneDeep
1 | |
JSON
1 | |
异常处理
throw抛异常
预估代码执行过程中可能发生的错误,会中断程序
1 | |
try/catch捕获异常
将可能错误的代码写到try,catch内写错误后的处理函数,不会中断程序;finally不管报错与否都会执行
1 | |
debugger
在代码中使用debugger,程序中断于debugger处
处理this
this指向
普通函数中this指向调用函数的对象,普通函数中无明确调用者时指向windows,在严格模式(use strict)中无明确调用者时返回undefind
箭头函数无this,函数内的this沿着作用域指向上一层this的值,箭头函数不适用于构造函数,原型函数,dom事件函数等等
改变指向
**fn.call(thisArg,arg1,arg2,…)**调用函数fn,thisArg是fn运行时指定的this值,其他arg为其他参数
**fn.apply(thisArg,[argsArray])**调用函数fn,thisArg是fn运行时指定的this值,其他参数必须包含在数组内
**fn.bind(thisArg,arg1,arg2,…)**不调用函数,返回指定的this值和初始化参数的新函数(原函数改造)