JavaScript经典面试题总结~(1)

前言

大家早上好!本篇文章将总结一些比较经典的JavaScript面试题,如果有帮助到你,留下你的一键三连。

JavaScript 面试题来了

1. 你理解 JavaScript 预编译中 AO 了吗?

请回答以下代码执行结果并做解释?

function fn(a){        //定义一个函数fn()
            console.log(a);
            var a = 123;
            console.log(a);
            function a() {}    //函数的声明在预编译时已经被识别,所以在调用fn(1)时,忽略这条语句
            console.log(a);
            var b  = function () {}  
            console.log(b);
            function d() {}
        }
        fn(1);
解:
1、创建一个AO对象。  AO {  }
2、找形参和变量声明,将变量和形参名作为AO的属性名,初始值为undefined。变量名和形参名一致的话只写一个就行。
    AO { 
     	a : undefined
     	b : undefined
         }
  3、将实参和形参统一。
    AO {
    	a : 1
    	b : undefined
      }
  4、在函数体里找函数声明,值(函数声明)赋予 AO 对象。
    AO {
    a : function a() {}
    b : undefined
     d : function d() {}
      }
预编译结束后,才执行fn(1)函数。(执行过程为从上到下依次执行)
执行结果为:function a() {} 、123、123、function () {}.
2.你理解的数组去重方法有哪几种?

请自定义一个随机数组并对数组中的元素进行去重

解:
1、双重fo循环,找到重复的就删除 (最为暴力的方式)

// 思想:利用两次循环,判断原数组中的元素是否相等,相等则去掉
var arr = [];
for( var m = 0; m < 15; m++){
    arr[m] = parseInt(Math.random()*10);
}
console.log(arr);

Array.prototype.forDescaling = function(){
    for(var i = 0; i < this.length - 1; i++){
        for(var j = 1 + i;j < this.length; j++){
            if( this[i] === this[j] ){
                this.splice(j,1);
                j --;
            }
        }
    }
}
arr.forDescaling();
console.log(arr);

2、利用对象属性名不冲突	(这种解答最优)
// 利用对象属性名,创建一个对象,利用对象属性名的唯一性完成去重

var arr = [];
for( var m = 0; m < 15; m++){
    arr[m] = parseInt(Math.random()*10);
}
console.log(arr);


Array.prototype.Obj = function (){
    var obj = {};
    var temp = [];
    for(var i = 0; i < this.length; i++){
        if(obj[this[i]] === undefined){
            obj[this[i]] = 1;
            temp.push(this[i]);
        }
    }
    return temp;
}
console.log(arr.Obj());

3、ES6(Set是一种新的数据类型,加强版数组,默认不允许重复。可能存在兼容性问题)

var arr = [];
for( var m = 0; m < 15; m++){
    arr[m] = parseInt(Math.random()*10);
}
console.log(arr);

Array.prototype.setDecsaling = function (){
    return Array.from(new Set(this));
}
console.log(arr.setDecsaling());
3.如何理解 JavaScript 中的 this ?

this 是 JavaScript 的关键字
它是根据执行上下文(执行环境)动态指向当前调用的对象;
谁调用,就指谁;
准确说就是调用位置,调用栈的指向。

1、全局this指window
console.log(this) 
function fn () {
      console.log(this) // window
}

2、事件里的this指向事件触发对象
 document.querySelector('div').onclick = function () {
      console.log(this)
  }

3、自调用函数this指window
;(function () {
      console.log(this)
    })()
    
function foo () {
      console.log(this)
    }
    
var obj = {
      foo
    }
    
var obj2 = {};
var obj2 = {};
    // 内部只是一个赋值,是外层的IIFE来调用的,所以this指向window
  (obj2.foo = obj.foo)()

4、对象方法的this指对象本身
    obj.foo()

5、构造函数的this以及构造函数原型方法里的this都是指向将来new的实例对象
    function Person (name) {
      this.name = name
    }
    Person.prototype.say = function () {
      console.log(this)
    }
    new Person('lisi')
    
6、没有归属的局部函数this指向window
    var dog = {
      name: 'mendou',
      say: function () {

        function getName () {
          console.log(this)
        }
        // getName这个方法没有归属的,所以就是window
        getName()
      }
    }
    dog.say()
7、箭头函数没有自己的this,指向自己的原型Object
    var dog = {
      name: 'mendou',
      say: function () {
        var getName = () => {
          console.log(this)
        }
        getName()
      }
    }
  dog.say()
4.全局变量和局部变量?

全局变量和局部变量各自有什么缺点?

全局变量:在函数体外定义的变量,每个函数都能使用修改,就会造成全局污染
局部变量:在函数体内定义的变量,只有当前函数能使用,但是不能在全局重复使用

5.继承有哪几种呢?
function Animal (name) {
    // 属性
    this.name = name;
    // 实例方法
    this.say= function(){
      console.log("My name is "+this.name);
    }
}
// 原型方法
Animal.prototype.eat = function(food) {
    console.log(this.name + '正在吃:' + food);
}

1 、原型链继承
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';


var cat = new Cat();
console.log(cat.name);
cat.say();
cat.eat('fish');
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

2 、构造继承
function Cat(name){
    Animal.call(this,name);
}

var cat = new Cat("Tom");
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

3、 组合继承(原型链和构造继承的组合)

function Cat(name){
    Animal.call(this,name);
}

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

// Test Code
var cat = new Cat();
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); // true

4 、寄生组合继承

function Cat(name){
    Animal.call(this);
    this.name = name;
}
(function(){
    // 创建一个没有实例方法的类
    var Super = function(){};
    Super.prototype = Animal.prototype;
    //将实例作为子类的原型
    Cat.prototype = new Super();
})();

// Test Code
var cat = new Cat();
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // true
console.log(cat instanceof Cat); //true

5、 拷贝继承
function Cat(name){
    var animal = new Animal(name);
    for(var key in animal){
        Cat.prototype[key] = animal[key];
    }
}
// Test Code
var cat = new Cat("Tom");
console.log(cat.name);
cat.say();
console.log(cat instanceof Animal); // false
console.log(cat instanceof Cat); // true

6、 ES6继承

var girl = function (name){
            this.name = name;
        }
        var boy = function(girl){
            this.girl = girl;
            this.send = function(gift){
                console.log("hello!"+this.girl.name+",送你一个"+gift);
            }
        }
        var proxyBro = function(girl){
            this.send = function(gift){
                new boy(girl).send(gift);
            }
        }
   var pro = new proxyBro(new girl("Lisa"));
          pro.send("么么哒");
          pro.send("玫瑰花");
6. JavaScript 的数据类型?

介绍下JavaScript的数据类型有那些,值是如何存储的?

JavaScript一共有8种数据类型,其中有7种基本数据类型:Undefined、Null、Boolean、Number、String、Symbol(es6新增,表示独一无二的值)和BigInt(es10新增);

1种引用数据类型——Object(Object本质上是由一组无序的名值对组成的)。里面包含 function、Array、Date等。JavaScript不支持任何创建自定义类型的机制,而所有值最终都将是上述 8 种数据类型之一。

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

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

7.JavaScript中的类型判断,你知道哪些呢?

JavaScript 中数据类型的判断

(1) typeof

typeof 对于原始类型来说,除了 null 都可以显示正确的类型
typeof 对于对象来说,除了函数都会显示 Object,所以说 typeof 并不能准确判断变量到底是什么类型,所以想判断一个对象的正确类型,这时候可以考虑使用 instanceof

(2)instanceof

instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。可以看出直接的字面量值判断数据类型,instanceof可以精准判断引用数据类型(Array,Function,Object),而基本数据类型不能被instanceof精准判断。

我们来看一下 instanceof 在 MDN 中的解释:instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。其意思就是判断对象是否是某一数据类型(如Array)的实例,请重点关注一下是判断一个对象是否是数据类型的实例。在这里字面量值,2, true ,‘str’ 不是实例,所以判断值为false。

(3)constructor


console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
这里有一个坑,如果我创建一个对象,更改它的原型,constructor就会变得不可靠了
function Fn(){};

Fn.prototype=new Array();

var f=new Fn();

console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true

(4)Object.prototype.toString.call()

使用 Object 对象的原型方法 toString ,使用 call 进行偷梁换柱,借用Object的 toString 方法

var a = Object.prototype.toString;

console.log(a.call(2)); // number
console.log(a.call(true)); // boolean
console.log(a.call('str')); // string
console.log(a.call([]));// Array 
console.log(a.call(function(){})); // Function
console.log(a.call({}));// Object
console.log(a.call(undefined));// undefined
console.log(a.call(null));// null

总结

本期 JavaScript 经典面试题总结就到这里,我们总结下:

  • 你理解 JavaScript 预编译中 AO 了吗?
  • 你理解的数组去重方法有哪几种?
  • 如何理解 JavaScript 中的 this ?
  • 全局变量和局部变量?
  • 继承有哪几种呢?
  • JavaScript 的数据类型?
  • JavaScript中的类型判断,你知道哪些呢?

努力回想以上问题的答案,看看你能不能快速得出答案~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值