函数原型
1 函数的prototype属性
每个函数都有一个prototype属性 默认指向一个空object空对象 (原型对象)
原型对象中有一个属性constructor 指向函数对象
2 给原型对象 添加属性(一般是方法)
函数的所有实例对象自动拥有所有原型中的属性(方法)
显式原型 隐式原型
每个函数function都有一个prototype即显式原型
每个对象都有一个__proto__即隐式原型
对象的隐式原型值为其构造函数的显式原型的值
程序员能直接操作显式原型 不能直接操作隐式原型(ES6之前)
原型链
访问一个对象的属性时 先在自身属性查找 找到返回
如果没有再沿着__proto__这条链向上查找 找到返回
如果最终没找到,到尽头Object的__proto__ 返回undefined
隐式原型链
查找对象的属性
所有函数的__proto__都是一样的 都是new Function
函数的显式原型对象指向对象 默认空的Object实例对象
但Object不满足
所有函数都是Function的实例 包含Function
Object的原型对象是原型链的尽头,为null
原型链_属性问题
读取对象的属性值时,自动到原型链中查找
设置对象的属性子时,不会查找原型链 如果当前对象没有此属性 直接添加该属性和值
方法一般定义在原型中 属性一般通过构造函数定义在对象本身上
变量提升与函数提升
变量提升
通过var定义 定义语句之前就可以访问到值undefined
函数声明提升
通过function 声明的函数 在之前就可以调用值函数定义(对象)
定义上下文 作用域与作用域链
一个代码段所在的区域
分类 全局作用域 函数作用域 块级作用域(ES6才有)
作用 隔离变量 不同作用域下同名变量不会冲突
闭包
1 当一个嵌套的内部函数引用了嵌套的外部函数的变量(或函数)时,就产生了闭包
2 闭包是什么?
闭包是嵌套的内部函数
闭包是包含被引用变量(函数)的对象
3 产生闭包的条件?
!!! 函数嵌套
!!! 内部函数引用了外部函数的数据(变量/函数)
执行函数定义就会产生闭包不用调用
常见的闭包
1 将函数作为另一个函数的返回值
2 将函数作为实参传递给另一个函数调用
闭包的作用
1 使用函数内部的变量在函数执行完后,仍然存活在内存中 延长局部变量的生命周期
2 让函数外部可以操作读写到函数内部的数据(变量/函数)
闭包的生命周期
产生 在嵌套内部函数定义执行完时就产生了
死亡 在嵌套的内部函数成为垃圾对象时 (object = null)
闭包的应用
1 具有特定功能的js文件
2 将所有的数据和功能都封装在一个函数内部
3 只向外暴露一个包信n个方法的对象或函数
4 模块使用者 只需通过模块暴露的对象调用方法来实现对应的功能
使用场景 setTimeout定时器 回调函数 函数防抖 封装私有变量
闭包的缺点内存溢出及解决
缺点 函数执行完后 函数内的局部变量没有释放占用内存时间会变长容易造成内存泄漏
解决 避免使用闭包 及时释放
内存溢出 一种程序运行出现的错误 当程序运行需要的内存超过了剩余的内存时 出现抛出内存溢出的错误
内存泄漏 占用的内存没有及时释放 内存泄漏多了就会导致内存溢出
常见的内存泄漏 多余的全局变量 没有及时清理的计时器或回调函数 闭包
console.log(Date.prototype.constructor === Date ,typeof Date.prototype)
function Fun() {
}
//给原型对象添加属性 一般是方法 ==》实例对象可以访问
Fun.prototype.test = function(){
console.log('test')
}
console.log(Fun.prototype)
var fun = new Fun()
fun.test()
function f() {
//内部语句 this.prototype = {}
}
console.log(f.prototype)
var fn = new f()
console.log(fn.__proto__)
console.log(f.prototype === fn.__proto__)
// 定义构造函数 创建实例对象 给原型添加方法 通过实例调用原型方法