1. 说一下JavaScript的数据类型有哪些
答: string,number,boolean,undefined,null,bigInt,symbol,object
JavaScript里面
number默认是双精度浮点数,不能够表示太大的数字。于是有了bigInt。需要注意的是bigInt只能表示任意大的整数。
2. 原型链是什么
1. 先讲一下原型。
首先定义一个对象obj。对象obj有一个隐藏属性,这里我先记作为 __xxx__ (大部分的浏览器定义为__proto__)。这个属性会指向Object.prototype。
const obj = {}
obj.__xxx___ = Object.prototype
因此可以得出结论: 对象 obj 的原型是 Object.prototype 。也可以说 Object.prototype 是对象 obj 的原型。
对象通过隐藏属性__xxx__就能找到自己的原型,这是该隐藏属性的唯一作用。
2.接下来解释下原型链
这里定义一个数组 array ,可以得到如下结论:
const array = []
array.__xxx__ = Array.prototype // Array.prototype 也是对象。所以也有隐藏属性__xx__
Array.prototype.__xxx__ = Object.prototype
因此这里的array就有两层原型,形成了原型链。
3.代码实现
const p = {
a:1,
b:2,
}
const obj = Object.create(p) // 指定 obj 的原型是 p
const obj = new Obj() // new 会将 obj 的隐藏属性__xx__ 指向 Obj.prototype
4.解决什么问题
在没有class的情况下可以实现继承。原型链上面可以挂在公共的属性,这样做可以实现复用,比如定义的数组array上面可以使用valueOf方法,该方法就是存在Object.prototype上面的。
5.优缺点
- 优点:实现起来很简单,清楚明了
- 缺点:跟class相比不支持私有属性
3. JavaScript中的new关键字做了啥
答: new关键字做了如下几点
- 创建了一个临时对象
- 绑定原型
- 将this 指向 这个临时对象
- 执行构造函数
- 返回这个临时对象
new 后面不可接箭头函数。箭头函数没有this指向,也没有 proptotype
function Person(name){
this.name = name
}
const p = new Person("vino")
//1. 创建临时对象
temp = {}
//2.绑定原型
temp.__proto__ = Person.prototype
//3.将this指向这个临时对象
this = temp
//4. 执行构造函数
this.name = "vino"
//返回 临时对象
p = temp
4. JavaScript中的立即执行函数是什么
答: 声明了一个匿名函数,然后立即执行该匿名函数,这就是立即执行函数。具体做法如下
(function (){console.log('a')}())
//或者前面使用 感叹号,加号,减号都是可以的
1.解决了什么问题
在 ES6之前,只能通过立即执行函数的方式来创建 局部作用域 。
!function f(){
var a = 1
}()
2.优缺点
- 优点: 兼容性好
- 缺点: 语法太丑,为了创建一个局部变量,害得执行一个函数
3. 代替方案
ES6里面的局部作用域
{
lat a = 1
}
5. JavaScript里面什么是闭包
闭包是JavaScript的一种语法特性
函数 + 自由变量 = 闭包 (变量分为:全局变量,自由变量,本地变量)
const add = function(){
let a
function add(){
a +=1
}
return add
}()
// 重构
const add = function(){
let a
return function add(){
a +=1
}
}()
上面代码实现了通过调用Api的方式来修改某个变量的值,这样做不会将变量直接暴露出去,而是暴露出操作对象的方法。
1.解决的问题
- 通过闭包可以提供对局部变量的间接访问
- 避免了污染全部环境(因为是局部变量)
- 维持了变量不会被垃圾回收(牵强)
2.优缺点
- 优点: 简单好用
- 缺点: 闭包使用不当 可能会造成内存泄漏(准确来说是旧版IE的bug)
6. JavaScript实现类
1. ES5
function Cat(name){
this.name = name
}
Cat.prototype.kind = "cat"
Cat.prototype.say = function(){console.log(this.name)}
const c = new Cat("橙子")
2. ES6
class Cat {
constructor(name){
this.name = name
}
say(){
console.log(this.name)
}
}
const c = new Cat("橙子")
7. JavaScript 如何实现继承
1.ES5
function Animal(kind){
this.kind = kind
}
function Dog(name){
Animal.call(this,'dog') //继承自身属性
this.name = name
}
// 面试官不想要的结果(__proto__ 不是所有的浏览器都叫这玩意)
Dog.prototype.__proto__ = Animal.prototype //共有属性继承
//面试官想要的答案
var temp = function(){} // 临时变量的目的,就是为了在new 的时候,不要添加额外的属性(kind)到原型上面
temp.prototype = Animal.prototype
Dog.prototype = new temp()
2. ES6
class Animal {
constructor(kind){
this.kind = kind
}
}
class Dog extends Animal {
constructor(name){
super('dog')
this.name = name
}
}