JS高频面试题

  1. 介绍一下js的数据类型有哪些,值是如何存储的

JavaScript一共有8种数据类型,其中有7种基本数据类型:

Undefined、Null、Boolean、Number、String、Symbol、Bigint

1种引用数据类型:Object

原始数据类型:直接存储在栈(stack)中,占据空间小、大小固定,属于被频繁使用数据,所以放在栈中存储。

引用数据类型:同时存储在栈(stack)和堆(heap)中,占据空间大、大小不固定。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,获取地址后从堆中获得实体。

  1. &&、||和!!运算符分别能做什么

&&叫逻辑与,在其操作数中找到第一个虚值表达式并返回它,如果没有找到任何虚值表达式,则返回最后一个真值表达式。它采用短路来防止不必要的工作。

||叫逻辑或,在其操作数中找到第一个虚值表达式并返回它,如果没有找到任何虚值表达式,则返回最后一个真值表达式。它采用短路来防止不必要的工作。在支持ES6默认函数参数之前,它用于初始化函数中的默认参数值。

!!运算符可以将右侧的值转换为布尔值,这也是将值转换为布尔值的一种简单方法。

  1. js的数据类型的转换

在JS中类型转换有三种情况:

转换为数字型:Number( )、parseInt( )、parseFloat( )

转换为布尔型:Boolean( )

转换为字符串:数据.toString( )

  1. JS中数据类型的判断

typeof

instanceof

  1. 介绍JS有哪些内置对象

js中的内置对象主要指的是在程序执行前存在全局作用域里的由js定义的一些全局值属性、函数和用来实例化其他对象的构造函数对象。一般我们经常用到的如全局变量值NaN、undefined, 全局函数如parselnt()、parseFloat() 用来实例化对象的构造函数如Date、Object等,还有提供数学计算的单体内置对象如Math对象。

6. undefined与undeclared的区别?

已在作用域中声明但还没有赋值的变量,是undefined。相反,还没有在作用域中声明过的变量,是undeclared的。

对于undeclared变量的引用,浏览器会报引用错误,如

ReferenceError: b is not defined。但是我们可以使用typeof的安全防范机制来避免报错,因为对于undeclared ( 或者not defined )变量, typeof 会返回"undefined"

7. null和undefined的区别?

首先Undefined和Null都是基本数据类型,这两个基本数据类型分别都只有一个值,就是undefined和null。

undefined代表的含义是未定义,

null代表的含义是空对象(其实不是真的对象,请看下面的注意! )。一般变量声明了但还没有定义的时候会返回undefined, null主要用于赋值给一些可能会返回对象的变量,作为初始化。

8. {}和[]的valueOf和toString的结果是什么?

{ }的valueOf结果为{ },toString的结果为"[object object] '

[ ]的value0f 结果为[ ],toString 的结果为””

9. Javascript的作用域和作用域链

作用域:作用域是定义变量的区域,它有一套访问变量的规则,这套规则来管理浏览器引擎如何在当前作用域以及嵌套的作用域中根据变量(标识符)进行变量查找。

作用域链:作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问,通过作用域链,我们可以访问到外层环境的变量和函数。

作用域链的本质上是一个指向变量对象的指针列表。变量对象是- -个包含了执行环境中所有变量和函数的对象。作用域链的前端始终都是 当前执行上下文的变量对象。全局执行上下文的变量对象( 也就是全局对象)始终是作用域链的最后一个对象。

当我们查找一个变量时,如果当前执行环境中没有找到,我们可以沿着作用域链向后查找

10. javascript创建对象的几种方式?

000

我们一般使用字面量的形式直接创建对象,但是这种创建方式对于创建大量相似对象的时候,会产生大量的重复代码。但js和一般的面向对象的语言不同,在ES6之前它没有类的概念。但是我们可以使用函数来进行模拟,从而产生出可复用的对象创建方式,我了解到的方式有这么几种:

(1)第一种是工厂模式,工厂模式的主要工作原理是用函数来封装创建对象的细节,从而通过调用函数来达到复用的目的。但是它有一个很大的问题就是创建出来的对象无法和某个类型联系起来,它只是简单的封装了复用代码,而没有建立起对象和类型间的关系。

(2)第二种是构造函数模式。js中每个函数都可以作为构造函数, 只要一个函数是通过 new来调用的,那么我们就可以把它称为构造函数。执行构造函数首先会创建一个对象, 然后将对象的原型指向构造 函数的prototype 属性,然后将执行上下文中的this指向这个对象,最后再执行整个函数,如果返 回值不是对象,则返回新建的对象。因为this 的值指向了新建的对象,因此我们可以使用this 给对象赋值。构造函数模式相对于工厂模式的优点是,所创建的对象和构造函数建立起了联系,因此我们可以通过原型来识别对象的类型。但是构造函数存在一个缺点就是,造成了不必要的函数对象的创建,因为在js中函数也是一个对象,因此如果对象属性中如包含函数的话,那么每次我们都会新建一个函数对象,浪费了不必要的内存空间,因为函数是所有的实例都可以通用的。

(3) 第三种模式是原型模式,因为每一个函数都有一个prototype 属性,这个属性是一个对象, 它包含了通过构造函数创建的所有实例都能共享的属性和方法。因此我们可以使用原型对象来添加公用属性和方法,从而实现代码的复用。这种方式相对于构造函数模式来说,解决了函数对象的复用问题。但是这种模式也存在一些问题,一个是没有办法通过传入参数来初始化值,另一个是如果存在一个引用类型如Array这样的值,那么所有的实例将共享一个对象,一个实例对引用类型值的改变会影响所有的实例。

(4)第四种模式是组合使用构造函数模式和原型模式,这是创建自定义类型的最常见方式。因为构造函数模式和原型模式分开使用都存在一些问题,因此我们可以组合使用这两种模式,通过构造函数来初始化对象的属性,通过原型对象来实现函数方法的复用。这种方法很好的解决了两种模式单独使用时的缺点,但是有一点不足就是,因为使用了两种不同的模式,所以对于代码的封装性不够好。

(5)第五种模式是动态原型模式,这一种模式将原型方法赋值的创建过程移动到了构造函数的内部,通过对属性是否存在的判断,可以实现仅在第一次调用函数时对原型对象赋值一次的效果。这种方式很好地对上面的混合模式进行了封装。

(6)第六种模式是寄生构造函数模式,这种模式和工厂 模式的实现基 本相同,我对这个模式的理解是 ,它主要是基于一个已有的类型,在实例化时对实例化的对象进行扩展。这样既不用修改原来的构造函数,也达到了扩展对象的目的。它的一个缺点和工厂模式一样,无法实现对象的识别。

11. JavaScript继承的几种实现方式?

..0

我了解的js中实现维承的儿种方式有:

(1)第种是以原型链的方式来实现继承,但是这种实现方式存在的缺点是,在包含有引用类型的数据公被所有的实例对象所共享,容易造成修改的混乱。还有就是在创建子类型的时候不能向超类型传递

(2)第二种方式是使用借用构造函数的方式,这种方式是通过在子类型的函数中调用超类型的构造函数来实现的,这一种方法解决了不能向超类型传递参数的缺点,但是它存在的一个问题就是无法实现函数方法复用,并且超类型原型定义的方法子类型也没有办法访问到。

(3)第三种方式是组合继承,组合继承是将原型链和借用构造两数组合起来使用的一种方式。通过借用构种方式解决了上面的两种极式单独使用时的问题,但是由于我们是以超类型的实例来作为子类型的原型,所以调用了两次超类的构造函数,造成了子类型的原型中多了很多不必要的属性。

(4)第四种方式是原型式继承,原型式继承的主要思路就是基于已有的对象来创建新的对象,实现的原理是,向函数中传入一个对象,然后返回一个以这个对象为原型的对象。这种维承的思路主要不是为了实现 创造一种新的类型,只是对某个对象实现种简单继承, ES5 中定义的0bject.create() 方法就是原型式继承的实现,缺点与原型链方式相同。

(5)第五种方式是寄生式继承,寄生式继承的思路是创建。个用于封装继承过程的函数,通过传入一个对 象,然后复制个对象的副本,然后对象进行扩展, 最后返回这个对象。这个扩展的过程就可以理解是一 种继承:这种维承的优点就是对一个简单对象实现谁承, 如果这个对象不是我们的自定义类型时,缺点是没有办法实现函数的复用。

(6)第六种方式是寄生式组合维承,组合继承的缺点就是使用超类型的实例做为子类型的原型,导致添加了不必要的原型属性:寄生式组合继承的方式是使用超类型的原型的副本来作为子类型的原型,这样就避

免了创建不必要的属性。

12.寄生式组合继承的实现?

functton Person(name) {

}

Person. prototype . sayName = function() {. onsole.log( "My name ts" +

this.name +" ." );

function Student( name, grade) { Person.call(thts, name);

thts.grade = grade;

Student. prototype = 0b ject. create( Person. prototype );

Student . prototype . sayMyGrade = function() {

console.log("My grade is“+ thts.grade + "." );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值