js面试:闭包,类,继承,立即执行函数

122 阅读2分钟

1.立即执行函数

如字面意思,声明一个函数然后立即执行

(function(){alert('我是匿名函数')} ())  // 用括号把整个表达式包起来
(function(){alert('我是匿名函数')}) ()  // 用括号把函数包起来
!function(){alert('我是匿名函数')}()    // 求反,我们不在意值是多少,只想通过语法检查。
+function(){alert('我是匿名函数')}()
-function(){alert('我是匿名函数')}()
~function(){alert('我是匿名函数')}()
void function(){alert('我是匿名函数')}()
new function(){alert('我是匿名函数')}()
var x = function(){return '我是匿名函数'}()

解决了什么问题:

在 ES6 之前,只能通过它来「创建局部作用域」。

2.闭包

一种语法特性

闭包=函数+自由变量

自由变量:有自己作用域的变量(相对的就是全局变量)

{
      let count
      function add (){ // 访问了外部变量的函数
        count += 1
      }
}
闭包

解决了什么问题:

  1. 避免污染全局环境。(因为用的是局部变量)
  1. 提供对局部变量的间接访问。(因为只能 count += 1 不能 count -= 1)
  1. 维持变量,使其不被垃圾回收。

优点:

简单,好用。

缺点:

闭包使用不当可能造成内存泄露。

注意,重点是「使用不当」,不是闭包。

3. js实现类

1.使用原型

function chicken(){
}
chicken.prototype.kind = '鸡'
chicken.prototype.say = () =>{console.log('打鸣')}
chicken.prototype.fly = () =>{console.log('扑腾')}

const c = new chicken()
c.say()
c.fly()
console.log(c.kind)

2.使用class

class chicken{
  constructor() {
    this.name = name
  }
  say(){console.log('打鸣')}
  fly(){console.log('扑腾')}
}
const c = new chicken()
c.say()
c.fly()
console.log(c.kind)

以我大学的学习习惯来说当然是经常使用2,但是1的话只要理解了原型链也是非常简单易懂的

4.继承

1.使用原型链

function Animal(legsNumber){
  this.legsNumber = legsNumber
}
Animal.prototype.kind = '动物'

function Dog(name){ 
  this.name = name
  Animal.call(this, 4) // 关键代码1
}
Dog.prototype.__proto__ = Animal.prototype // 关键代码2,但这句代码被禁用了,怎么办

Dog.prototype.kind = '狗'
Dog.prototype.say = function(){
  console.log(`汪汪汪~ 我是${this.name},我有${this.legsNumber}条腿。`)
}

const d1 = new Dog('啸天') // Dog 函数就是一个类
console.dir(d1)

如果面试官问被 ban 的代码如何替换,就说下面三句:

var f = function(){ }
f.prototype = Animal.prototype
Dog.prototype = new f()

2.使用 class

class Animal{
  constructor(legsNumber){
    this.legsNumber = legsNumber
  }
  run(){}
}
class Dog extends Animal{
  constructor(name) {
    super(4)
    this.name = name
  }
  say(){
    console.log(`汪汪汪~ 我是${this.name},我有${this.legsNumber}条腿。`)
  }
}