递归、闭包、原型、继承本文主要讲解和阐明函数的一些常用知识点:递归,什么是闭包,闭包使用场景,什么是原型和原型链,如何实现继承,原理传承,原创。递归函数的递归就是在函数中调用自己。举个例子。如何获得著名的斐波那契数列。问题是这样的:正月初一,有一对刚出生的兔子。过了二个月(三月初)就可以生产了。每对能生育的兔子每个月都会产下一对新的兔子。兔子永远不会死。定义的序列是我们需要在n个月内找到多少对兔子。Functionfn(n){可以通过递归算法得到returnn<2?1:fn(n-1)+fn(n-2)}varcount=fn(30);控制台日志(计数);闭包什么是闭包?闭包是一个函数,它可以在声明它的函数范围内继承和访问变量。functionfn1(){vara='hello'functionfn2(){console.log(a)}}fn1()//其中fn2是闭包函数的使用场景closure闭包的使用场景有很多种,下面举例:1.私有变量functionPerson(){varname="default";return{getName:function(){返回名称;},setName:function(newName){名称=newName;}}};varperson=Person()console.log(person.getName())//defaultperson.setName('xiaomuchen')console.log(person.getName())//xiaomuchenvarperson2=Person()console.log(person2.getName())//default上面的函数使用一个闭包来创建一个私有变量名。变量不能被外界直接操作或获取,只能通过返回的接口进行控制。2.匿名自执行函数比如开发一个页面,需要在页面初始化的时候立即做一些操作,那么可以在页面中使用一个匿名自执行函数,当JS引擎启动时会立即执行读取这部分代码实现。//添加页面打开时间到标题(function(){varopenTime=newDate()document.title=document.title+openTime})();原型、原型链、继承先问一个问题:__proto__和原型会在哪里出现?他们之间是什么关系?实现继承依赖于什么?__proto__和prototype的区别1.JavaScript中的每一个对象都有一个原型链(__proto__)指向其构造函数的原型(prototype)vara={}a.__proto__===Object.prototype//truefunctionPerson(){}Person.__proto__===Function.prototype//truevarp=newPerson()p.__proto__===Person.prototype//true2.JavaScript中的每一个函数都有一个原型(prototype),原型也是一个对象。包括:原型链、原型方法(property)、函数构造,同样它的原型链指向原型函数Person(){}Person.prototype.getName=function(){}Object.getOwnPropertyNames(Person.prototype)//["constructor","getName"]Person.prototype.__proto__===Object.prototype//true3.访问函数的属性时,首先尝试访问其自身的属性,然后再尝试访问其原型属性。访问对象的属性时,首先尝试访问其自身的属性,然后尝试通过原型链访问其构造函数原型上的属性。如果没有,请遍历原型上的原型链并继续搜索,直到访问Object.prototype上的属性。如果不是,因为Object.prototype是没有__proto__的对象,所以查询到此结束,返回undefined。functionPerson(){}Person.getName=function(){console.log('Person1')}Person.prototype.getName=function(){console.log('Person2')}varp=newPerson()Person.getName()//Person1p.getName()//Person2console.log(typeofp.getClass)//undefinedInheritedJavaScript函数通过原型和原型链函数实现继承superA(name){this.name=name}superA.prototype.getName=function(){console.log(this.name)}functionsubA(name){superA.call(this,name)//继承的属性}subA.prototype=newsuperA()//继承的方法vara1=newsubA('xiaomuchen')a1.getName()//上面xiaomuchen的代码描述了一个函数的经典继承,其工作原理如下:声明父类superA,子类subA重写子类subA的原型,并指向superA的Instance,在实例化a1时,a1.__proto__=>subA.prototype=>newsuperA()=>superA.prototype,所以a1的构造函数是superA,同时运行subA的是superA.call(this,'xiaomuchen'),其中this指向a1,所以a1继承了name属性,所以子类subA的实例a1继承了superA的原型方法和属性。为了帮助你接受更多的东西,我们将在下一章更深入地讨论函数。作者:肖木辰,github。
