1。前言这段时间面试了很多人,也有很多人分享面试题。前段时间,我也临时担任过面试官。为了大概了解面试官的水平,我也写了个题目,面试了几位前端开发。这段时间在学习和写设计模式的一些知识。意想不到的设计模式知识是面试题中经常让人掉坑的考点。所以,今天我就总结一下那些让人掉坑里的测试点。2、面向对象编程关于面向对象和面向过程,我个人感觉两者不是绝对独立的,而是相辅相成的。至于什么时候用面向对象,什么时候用面向过程,要具体情况具体分析。对于面向对象编程。知乎上有个高赞答案:面向对象:狗。eat(shit)面向过程:吃。(dog,shit)但是这个例子感觉不是很优雅,我改了一下,举个优雅的小例子来说明面向对象和面向过程的区别。需求:定义“等着吃火锅”的面向对象思想:waiting。Action(吃火锅)面向过程的思想是:action(等待,吃火锅)}//ActionPeople.prototype={eat:function(someThing){console.log(`${this.name}eats${someThing}`);}}//Shouhou是一个人,所以创建一个人(newoncePeople)letshouhou=newPeople('waiting','male',24);shouhou.eat('火锅');//面向过程leteat=function(who,someThing){console.log(`${who}eats${someThing}`);}eat('waiting','hotpot');结果一样,都是输出'等着吃火锅'。但以防万一我现在吃饱了并准备好编码。现在如何实现?看代码//面向对象shouhou.coding=function(){console.log(this.name+'写代码');}shouhou.coding();//面向过程letcoding=function(who){console.log(who+'写代码');}coding('等待');结果是一样的:'等着写代码'但是不难发现面向对象更灵活,可重用和可扩展。因为面向对象就是对对象进行一定的动作(例子中:'waiting')。这些操作可以自定义扩展。而面向过程就是定义了很多动作来指定谁来执行这个动作。好了,面向对象的简单描述到此结束,至于面向对象的三大特性:继承、封装、多态,这个就自己去网上找资料了。3、this在使用JavaScript开发的时候,很多开发者或多或少会对this的方向感到困惑,但其实关于this的方向,记住最核心的一句话:哪个对象调用了一个函数,函数中的this要指向哪个对象。3-1.对于指向全局对象窗口的普通函数调用,没有特别的意外。letusername='waiting'functionfn(){alert(this.username);//undefined}fn();可能大家会疑惑,为什么不输出waiting,但是仔细一看,我声明的方式是let,而不是如果是window对象,如果输出waiting,写varusername='waiting'functionfn(){alert(this.username);//waiting}fn();//-------------window.username='waiting'functionfn(){alert(this.username);//waiting}fn();3-2.对象函数调用不难理解,就是函数调用,this指向window.where。b=2222letobj={a:111,fn:function(){alert(this.a);//111alert(this.b);//undefined}}obj.fn();很明显,第一次是输出obj.a是111,第二次obj没有b属性,所以输出undefined,因为this指向obj。但是要注意下面的情况;//222这个不难理解,虽然obj1.fn是从obj2.fn赋值过来的,但是函数是obj1调用的,所以this指向obj1。3-3。构造函数调用letTestClass=function(){this.name='111';}letsubClass=newTestClass();subClass.name='waiting';console.log(subClass.name);//等待letsubClass1=newTestClass();console.log(subClass1.name)//111这个不难理解,回想一下(new的四个步骤)都差不多!但是有个坑,虽然一般不会出现,但是还是有必要提一下。在构造函数中返回对象会直接返回对象,而不是3-4构造函数执行后创建的对象。apply和call调用apply和call只是改变传递函数的this。letobj1={a:222};letobj2={a:111,fn:function(){alert(this.a);}}obj2.fn.call(obj1);此时虽然是obj2的call方法,但是使用call,动态的将this指向obj1。相当于这个obj2.fn这个执行环境是obj1。申请和通话详情如下所述。3-5。箭头函数调用首先ES6提供了箭头函数,增加了我们的开发效率,但是箭头函数中没有this,箭头函数中的this继承了外部环境。一个例子letobj={a:222,fn:function(){setTimeout(function(){console.log(this.a)})}};obj.fn();//undefined不难找到,虽然this里面的fn()指向obj,但是传给setTimeout的是普通函数,this指向window,没有underwindow,所以这里输出undefined。换成箭头函数letobj={a:222,fn:function(){setTimeout(()=>{console.log(this.a)});}};obj.fn();//这次输出222222是因为箭头函数传给了setTimeout,而箭头函数里面没有this,所以需要往上层作用域查找。本例中setTimeout的上层作用域为fn。而fn中的this指向obj,所以setTimeout中箭头函数的this指向obj。所以输出222。4.call和applycall和apply的功能完全一样,只是参数不同而已。call接收到的参数不是固定的。第一个参数是函数体中this的指针,第二个参数之后依次传递后面的参数。apply接收两个参数,第一个参数也是函数体中this的指针。第二个参数是一个集合对象(数组或类数组)letfn=function(a,b,c){console.log(a,b,c);}letarr=[1,2,3];如上示例letobj1={a:222};letobj2={a:111,fn:function(){alert(this.a);}}obj2.fn.call(obj1);call和apply的两个主要目的是1.改变this的方向(把this从obj2指向obj1)2.方法借用(obj1没有fn,只是借用obj2的方法)5.ClosureClosure这个可能会让人迷惑每个人,可是必须要被征服的概念!让add=(function(){letnow=0;return{doAdd:function(){now++;console.log(now);}}})()执行几次!从上图可以看出,now变量在函数执行时并没有被回收,而是继续保存在内存中。具体原因如下:刚进来的时候,因为是自动执行函数,所以刚进来的时候会自动执行,然后赋值给这个对象add。因为add中有函数依赖于现在的变量。所以现在不会被销毁,回收。这是闭包(连续变量循环)的用途之一。由于now不能被外部访问,这就是闭包的另一种用途(创建局部变量,保护局部变量不被访问和修改)。有些人可能会有疑问,闭包会导致内存泄漏。但是仔细想想,在上面的例子中,如果不使用闭包,就需要使用全局变量。将变量放入闭包和全局变量中具有相同的效果。使用闭包可以减少全局变量,所以上面的例子闭包更好!6.总结在学习设计模式的时候,我遇到的知识点就这些。这些知识点也是让人在群聊和社区中掉入更多陷阱的考点。这些知识在开发中可以说是经常用到,在面试中也经常考到。建议您多了解一下。上面也是一个简单的pass。不太深。如果您对文章有什么建议,欢迎指出。
