一、js原型和原型链
1、原型讲解:
普通的对象:是没有prototype属性的,只有隐藏属性__proto__,
原型对象:person.prototype还有constructor属性,属于普通对象
函数对象:所有的函数都拥有__proto__、prototype属性(指向原型对象)
其实原型对象就是构造函数的一个实例对象;
例如:
a和b,都得到了Dog对象的实例,这时a和b等于Dog的原型对象,a.name相当于获取的是原型对象上的name;b.name赋值的时候,相当于是在构造函数Dog里添加了新的name属性
实例 ,原型对象,构造函数的关系:
实例的__proto__指向原型对象,原型对象的__proto__指向构造函数,如图:
2、原型链是实现继承的主要方法
原型链的基本思路:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针(constructor),而实例对象都包含一个指向原型对象的指针(__ptoto__),如果让原型对象等于另一个类型的实例,此时的原型对象将包含另一个指向原型的指针(__ptoto__),另一个原型也包含着一个指向另一个构造函数的指针(constructor)。假如另一个原型又是另一个类型是实例...,这就构成了原型与实例的链条。
如图:
二、js作用域和闭包
1、执行上下文
变量提升:
一个<script></script>标签为一个执行上下文,js在执行第一行代码的时候,会将所有定义的变量,声明的函数先提取出来,这个行为叫变量提升
变量提升在不同的方面,影响也不同:
变量声明:使用var,let,const关键字
函数声明:使用function(){}语法
类声明:使用class关键字
这些详细的区别:
使用var声明的变量会被提升到所在函数作用域的顶部。如果声明之前访问该变量。它的值会是undefined。
使用let,const声明的变量会被提升到所在块级作用域的顶部。如果声明之前访问该变量则会报错。
函数声明的提升允许在所属作用域内的任何地方使用该函数,不会抛出异常
类声明也会被提升到块级作用域的顶部,在声明之前使用类,会抛出异常
2、this
this在执行的时候才能确定,定义时无法确定
this在构造函数,对象,函数中使用的区别
call,apply,bind的区别
3、作用域,作用域链
js没有块级作用域,只有函数和全局作用域
js采用函数作用域
js中如果函数中嵌套函数就会出现作用域链
4、闭包
js闭包就是在另一个作用域中保存它从上级函数或作用域得到的变量,而这些变量是不会随上一级函数执行完成而销毁。
闭包就是在函数内部对外部作用域上变量的引用,使其常驻内存中,得不到释放。
例:
上面代码中,在函数体内定义另外的函数作为目标对象的方法函数,而这个对象的方法函数反过来引用外层函数体中的临时变量,当其中一个这样的内部函数在包含它们外部函数之外被调用时,就会形成闭包。
js的垃圾回收原理:
在js中如果一个对象不再被引用,那么这个对象会被GC回收,如果两个对象互相引用,而不再被第三者使用,那么这两个互相引用的对象也会被回收。在js中使用闭包,会给js的垃圾回收制造难题,尤其遇到对象间复杂的循环引用时,搞不好会造成内存泄漏。