高频前端面试题汇总之JavaScript篇

1.JavaScript有哪些数据类型,它们的区别?

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

其中 Symbol 和 BigInt 是ES6 中新增的数据类型:

  • Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
  • BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

这些数据可以分为原始数据类型和引用数据类型:

  • 栈:原始数据类型(Undefined、Null、Boolean、Number、String)
  • 堆:引用数据类型(对象、数组和函数)

两种类型的区别在于存储位置的不同:

  • 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
  • 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

  • 在数据结构中,栈中数据的存取方式为先进后出。
  • 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。

在操作系统中,内存被分为栈区和堆区:

  • 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
  • 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
2.比较操作符 “===”、“==” 的区别?
  • 使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
  • 使用三等号(===)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
3.常见的数组去重
  1. new set()去重

     var arr = [1,9,8,8,7,2,5,3,3,3,2,3,1,4,5,444,55,22];
     
      console.log(arr);   
     
      function noRepeat(arr){
     
        var newArr = [...new Set(arr)]; //利用了Set结构不能接收重复数据的特点
     
        return newArr
     
      }
     
      var arr2 = noRepeat(arr)
     
      console.log(arr2); 

  2. 利用 filter() 去重
  • filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。item是当前元素的值,index是当前元素的索引值。indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。利用indexOf() 查询到数组的下标,看是否等于当前的下标,相等的话就返回,否则不返回值
  • var arr = ['apple','apps','pear','apple','orange','apps'];
     
    console.log(arr)    
      var newArr = arr.filter(function(item,index){
         return arr.indexOf(item) === index;  // 因为indexOf 只能查找到第一个  
      });
     
    console.log(newArr); 

    3.利用for循环,搭配indexOf去重

  •  var arr = [1,9,8,8,7,2,5,3,3,3,2,3,1,4,5,444,55,22];
     function noRepeat(arr) {
    		//定义一个新的临时数组 
    		var newArr=[]; 
    		//遍历当前数组 
    		for(var i=0;i<arr.length;i++) {
    		  //如果当前数组的第i已经保存进了临时数组,那么跳过,
    		  //否则把当前项push到临时数组里面 
    		  if(newArr.indexOf(arr[i]) === -1) {  //indexOf() 判断数组中有没有字符串值,如果没有则返回 -1 
    		     newArr.push(arr[i]);
    		  }
        	}
        return newArr
      }
      var arr2 = noRepeat(arr);
      console.log(arr2);  

    4.利用includes实现数组去重

  •  var arr = [1,9,8,8,7,2,5,3,3,3,2,3,1,4,5,444,55,22];
        function noRepeat(arr) {
          let newArr = [];
          for(i=0; i<arr.length; i++){
            if(!newArr.includes(arr[i])){
                newArr.push(arr[i])
            }
          }
         return newArr
       }
     console.log(noRepeat(arr));
4.创建对象的方式?

1.对象字面量

       // 字面量创建对象
        var obj = {
            name: "张三",
            age: 20,
            sty() {
                console.log(this.name + "爱睡觉");
            }
        }
        obj.sty()

2.new关键字

let object = new Object();

3.构造函数

function Person(name){
   this.name = name;
   this.age = 21;
}
let object = new Person("小明");  

4.ES6的class类创建对象

       // 类 Person
        class Person {
            // 构造函数
            constructor(name, age) {
                // 实例成员
                this.name = name
                this.age = age
            }
            // 原型成员
            eat() {
                console.log(this.name + "爱睡觉");
            }
            // 静态成员
            static shows() {
                // 静态成员this指向构造函数Person
                console.log(this.name + "爱吃饭");
            }
        }
        // 实例化
        var p = new Person("小白", 10)
        console.log(p);
        p.eat()
        //静态成员只能通过构造函数调用
        Person.shows()

5.工厂函数创建对象

 
        // 工厂函数 通过改变参数多次使用
        function fun(name, age, gender) {
            var obj = new Object()
            obj.name = name
            obj.age = age
            obj.gender = gender
            // 返回一个对象 创建的就是对象类型+
            return obj
        }
        var p1 = fun("张三", 20, "男")
        var p2 = fun("李四", 30, "女")
        console.log(p1, p2);
        console.log(typeof (p1));

6.基于原型对象的模式

function Person() {
	// 通过 prototype 属性增加属性和函数
	Person.prototype.name = 'Tom';
	Person.prototype.age = 100;
	Person.prototype.getAge = function() {
		return this.name;
	}
};

// 生成两个实例
const person1 = new Person();
const person2 = new Person();

console.log(person1.name === person2.name);     // true
console.log(person1.getAge === person2.getAge); // true

通过上面的代码可以发现,使用基于原型对象的模式创建的实例,其属性和函数都是相等的,不同的实例会共享原型上的属性和函数,解决了方法 4 存在的问题。

但是该方法也存在一个问题,因为所有的实例会共享相同的属性,那么改变其中一个实例的属性值,便会引起其它实例的属性值的变化,这并不是我们期望的。
7.混合模式(构造函数+原型)

构造函数和原型混合的模式是目前最常见的创建自定义类型对象的方式。

构造函数中用于定义实例的属性,原型对象中用于定义实例共享的属性和方法,通过构造函数传递参数,这样每个实例都能拥有自己的属性值,同时实例还能共享方法的引用,最大限度的节约了内存的空间,混合模式保存了两者的优点。

// 构造函数中定义实例的属性
function Person(name, age) {
	this.name = name;
	this.age = age;
}

// 原型中添加实例共享的函数
Person.prototype.getAge = function () {
	return this.age;
}

// 生成两个实例
const person1 = new Person('Tom', 100);
const person2 = new Person('Lihua', 100);
5.new都干了什么?
  1. 创建一个对象
  2. 将构造函数的this指向这个对象
  3. 将对象的原型指向构造函数的原型
  4. 返回该对象
6.说说你对DOM的理解,常见的操作有哪些?

1.是什么?

  • DOM是一个对象,是HTML和XML文档的编程接口,其提供了一个结构化的表述并且定义了一种方式——程序可以对结构树进行访问,以改变文档的结构,样式和内容 从本质上说,它将web页面和脚本或编程语言连接起来了。

2.常见的操作

  • 创建节点
  • createElement createTextNode createDocumentFragment createAttributr
  • 查询节点
  • querSelector
  • 更新节点
  • innerHTML
  • 添加节点
  • appendChild
  • 删除节点
  • removeChild

        

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值