面试回答技巧(一) 如何回答的一个技术记汇,或者你对xxxx的理解? 例如:你说一下对闭包的理解? 答:1.xxx是什么? 2.应用场景 3.优缺点 4.具体实现 5.还有没有更好的解决方案!
今天的内容都是从这几个方面来讲解。
函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起构成闭包(closure)。也就是说,闭包可以让你从内部函数访问外部函数作用域。在 JavaScript 中,每当函数被创建,就会在函数生成时生成闭包。
总结来说:闭包就是函数加词法作用域。只要符合这两种情况基本上都是闭包。
那么什么是词法作用域呢?这里就来说说,看下面的代码:
function init() { var name = "张三"; // name 是一个被 init 创建的局部变量 function displayName() { // displayName() 是内部函数,一个闭包 alert(name); // 使用了父函数中声明的变量 } displayName(); } init();init() 创建了一个局部变量 name 和一个名为 displayName() 的函数。displayName() 是定义在 init() 里的内部函数,并且仅在 init()函数体内可用。请注意,displayName() 没有自己的局部变量。然而,因为它可以访问到外部函数的变量,所以displayName() 可以使用父函数 init() 中声明的变量 name 。
总结: 词法作用域:即以变量声明定义的位置为参照,如果当前位置没有定义,就会访问父级定义的位置。
闭包又分为广义和狭义两种:
a、广义的闭包:
var a=1000; function fn1() { alert(a) } fn1()b、狭义的闭包:
平时工作中用到的闭包是狭义上的闭包:
1.函数内嵌套函数 2.子函数引用了父函数的相关变量
符合上面的条件都是狭义的闭包。
特点:长期驻留内存
优点:
1.长期驻留内存,可以缓存数据 2.可以隔离作用域,避免全局污染
缺点:
长期使用,会造成内存泄漏。
解决内存泄漏的方法: 链接:https://www.jianshu.com/p/d903be89f211 上面的链接,自我感觉可以。
使用ES6的let方法,可以有效的避免。
https://www.jianshu.com/p/08c07a953fa0
每个对象都可以有一个原型_proto_,这个原型还可以有它自己的原型,以此类推,形成一个原型链。查找特定属性的时候,我们先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去向原型对象的原型对象里去寻找… 这个操作被委托在整个原型链上,这个就是我们说的原型链了。
原型链是JS特有的一种继承机制。原型链会涉及到__proto__,prototype。原型链的顶端就是null。继承
ES6推出class extends来实现继承。
继承是面向对象开发思想的特性之一。 面向对象的三大特点:封装、继承、多态(多种状态)。
缺点: 1、不能传参 2、 没有解决对象引用问题
借用构造函数继承 //创建一个父类 function Parent(name) { this.name=name ||'jack' this.colors=['red','green','blue'] } Parent.prototype.getName=function() { return this.name; } //创建一个子类 function Child(name) { //借用父类来承继实例属性,但不能继承父类方法 Person.call(this,name) }缺点:不能继承父类方法
组合继承(原型链继承 + 借用构造函数) //创建一个父类 function Parent(name) { this.name=name ||'jack' this.colors=['red','green','blue'] } Parent.prototype.getName=function() { return this.name; } var p1=new Parent(); p1.getName(); //创建一个子类 function Child(name) { Parent.call(this,name) } Child.prototype=new Parent(); var c1=new Child() c1.getName()优点:既能继承父类的原型和方法,也能传递参数属性。
通过class,extends,super实现 //继承必须要写super
//创建一个父类 class Parent { constructor(name) { this.name=name ||'jack' this.colors=['red','green','blue'] } getName() { return this.name; } } //创建一个子类 class Child extends Parent { constructor(name) { super(name) //super就是父类Parent } getValue() { } }