JS面向对象-原型和闭包
2019-01-02 13:08:19 42 举报
AI智能生成
JavaScript原型和闭包
作者其他创作
大纲/内容
“一切都是对象”理解
按照类型划分
值类型(非对象)
undefined, number, string, boolean
undefined, number, string, boolean
引用类型(对象)
函数、数组、对象、null、new Number(10)、new String("1")、new Array(1)
两种判断是否对象方法
typeof
当返回时"function"或者"object"说明是引用类型对象
instanceof
对象是若干属性的集合
数组、函数等都是对象,对象还是对象。像Number、Array、Function等这些函数,就是js默认的内建对象,可以直接使用
对象里面的一切都是属性,方法也是属性,依然表示为键值对的形式
函数也可以有对象属性,其中JQ中的$就是一个函数,$.trim()中的trim()就是函数$中的一个方法属性
函数和对象的关系
对象都是通过函数创建
对象字面值方式只是一种语法糖 var obj = {name='wuzhazha',age=25},等价于var obj = new Object()形式
Object、Array都是函数
prototype原型
每个函数都有一个prototype属性,该属性也是一个对象,即原型。默认含有一个constructor属性,指向函数本身
constrcutor的探讨
JS constructor探讨(一):为什么要设置prototype.constructor?
JS constructor探讨(二):再谈构造函数prototype.constructor的用途
隐式原型
每个对象都有一个__proto__,称为隐式原型,都指向创建该对象的函数的prototype
函数中的prototype也是一个对象,依然拥有__proto__属性
自定义函数的prototype本质上就是和 var obj = {} 是一样的,都是被Object创建,所以它的__proto__指向的就是Object.prototype。Object.prototype是一个特例,它的__proto__指向的是null
函数也是一个对象,也是被创建出来的,因此也有__proto__属性,指向的是Function
函数创建的两种方式
function fn(x,y){return x+y;}比较常用的函数创建方式,推荐
var fn = new Function("x","y","return x+y;");这种方式证明了函数可以使用js提供的Function内建对象创建
Function.prototype的__proto__是Object创建的,因此指向了Object.prototype
继承
instanceof原理
Instanceof运算符的第一个变量是一个对象,暂时称为A;第二个变量一般是一个函数,暂时称为B。Instanceof的判断规则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false
js的继承是基于原型链
访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链
判断属性是否来自该对象还是来自原型链上的对象,可以使用hasOwnProperty。所有对象都有hasOwnProperty方法,继承自Object.prototype
ES5和ES6中的继承探讨
es5继承
es6继承
this
全局环境下调用,代表的是window对象
全局变量是window对象的属性
全局函数是window对象的方法
this是上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境,this的取值都会有所不同
构造函数中,this就代表它即将new出来的对象,如果作为普通函数调用,则this就代表window对象
函数作为对象的一个属性,此时this代指向的是这个对象本身
函数用call或者apply调用,this的值就是传入的对象
全局 & 调用普通函数,this都指向window对象
在函数的prototype的函数使用this,代表的是当前的对象
执行上下文
执行上下文也叫执行上下文环境
执行上下文就是浏览器在执行运行js代码前做的准备工作,主要是三个点
变量、函数表达式--变量声明,默认赋值为undefined;
this--赋值
函数声明--赋值
js执行代码段之前都会通过“准备工作”来生成执行上下文。这个“代码段”其实分三种情况
全局代码
函数
函数生成执行上下文环境还需要添加三点
参数--赋值
arguments--赋值
自由变量的取值作用域--赋值
eval代码
执行上下文栈
执行全局代码时,会产生一个执行上下文环境,每次调用函数都又会产生执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境。处于活动状态的执行上下文环境只有一个
作用域
javascript没有块级作用域,所以我们在编写代码的时候,不要在“块”里面声明变量,要在代码的一开始就声明好了。以避免发生歧义
javascript除了全局作用域之外,只有函数可以创建的作用域。
所以,我们在声明变量时,全局代码要在代码前端声明,函数中要在函数体一开始就声明好。除了这两个地方,其他地方都不要出现变量声明。而且建议用“单var”形式
所以,我们在声明变量时,全局代码要在代码前端声明,函数中要在函数体一开始就声明好。除了这两个地方,其他地方都不要出现变量声明。而且建议用“单var”形式
作用域有上下级的关系,上下级关系的确定就看函数是在哪个作用域下创建的。例如,fn作用域下创建了bar函数,那么“fn作用域”就是“bar作用域”的上级
作用域最大的用处就是隔离变量。不同作用域下同名变量不会有冲突
如jQuery源码的最外层是一个自动执行的匿名函数。在jQuery源码中,声明了大量的变量,这些变量将通过一个函数被限制在一个独立的作用域中,而不会与全局作用域或者其他函数作用域的同名变量产生冲突。
全世界的开发者都在用jQuery,如果不这样做,很可能导致jQuery源码中的变量与外部javascript代码中的变量重名,从而产生冲突
全世界的开发者都在用jQuery,如果不这样做,很可能导致jQuery源码中的变量与外部javascript代码中的变量重名,从而产生冲突
作用域和执行上下文关系
除了全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数调用时确定
作用域只是一个“地盘”,一个抽象的概念,其中没有变量。要通过作用域对应的执行上下文环境来获取变量的值。同一个作用域下,不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值。所以,作用域中变量的值是在执行过程中产生的确定的,而作用域却是在函数创建时就确定了。所以,如果要查找一个作用域下某个变量的值,就需要找到这个作用域对应的执行上下文环境,再在其中寻找变量的值
自由变量和作用域链
在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。如上程序中,在调用fn()函数时,函数体中第6行。取b的值就直接可以在fn作用域中取,因为b就是在这里定义的。而取x的值时,就需要到另一个作用域中取,要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”。这就是所谓的“静态作用域”
在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量。如上程序中,在调用fn()函数时,函数体中第6行。取b的值就直接可以在fn作用域中取,因为b就是在这里定义的。而取x的值时,就需要到另一个作用域中取,要到创建这个函数的那个作用域中取值——是“创建”,而不是“调用”。这就是所谓的“静态作用域”
上面描述的只是跨一步作用域去寻找。如果跨了一步,还没找到呢?——接着跨!——一直跨到全局作用域为止。要是在全局作用域中都没有找到,那就是真的没有了。这个一步一步“跨”的路线,我们称之为——作用域链
闭包
闭包解释
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁--百度百科
闭包的两种用法
函数作为返回值
bar函数作为返回值,赋值给f1变量。执行f1(15)时,用到了fn作用域下的max变量的值
函数作为参数被传递
fn函数作为一个参数被传递进入另一个函数,赋值给f参数。执行f(15)时,max变量的取值是10,而不是100
闭包的用途
读取函数内部的变量
让变量的值始终保持在内存中
注意点
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除
闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值
参考资料
阮一峰闭包相关
廖雪峰闭包相关
博客园孤傲苍狼关于闭包的学习笔记-对阮一峰闭包文章的补充说明
国外一份关于闭包说明的ppt
在JavaScript中,我们声明的JavaScript全局对象、全局函数以及全局变量均自动成为window对象的成员
Js中的自定义函数、内建对象Object、Number等,这些也都是函数,都是Function函数对象创建出来的,因此它们的__proto__都指向了Function.prototype。如Object.__proto__ === Function.prototype//true。而Functiond函数,也是由Function函数创建出来,因此它的__proto__指向了Function.prototype

收藏
0 条评论
下一页