前端面试笔试复习(3)

JS 复习:

12、JS 有哪些数据类型

七种数据类型:number、string、boolean、object、null、undefined、symbol

obj 包括了数组、函数、正则、日期等对象。

13、Promise 怎么使用?

Promise 是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。

之所以有Promise 出现,是因为虽然异步(Async)回调有很高的执行效率,但同时却减少了程序的可读性。如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加一层嵌套下去。
创建一个promise对象

function promise(){
    return new Promise(function(resolve,reject){
          setTimeout(()=>{
              resolve()或者reject()
               },3000)       
 })

promise.then().catch()

具体例子

14、async/await 语法了解吗?目的是什么?

使用async / await, 搭配promise, 可以通过编写将异步流程处理为同步流程, 提高代码的简洁性和可读性.

await
await操作符用于等待一个Promise对象, 它只能在异步函数async function内部使用.

需要注意的是,await在等待 Promise 对象时会导致async function暂停执行, 一直到 Promise 对象决议之后才会async function继续执行.

代码实例:

async function showData() {
    // 假装请求数据1
    var data1 = await new Promise((resolve) => {
        setTimeout(() => {
            resolve('data1');
        }, 1000);
    });

    // 假装请求数据2且此请求依赖数据1
    var data2 = await new Promise((resolve) => {
        setTimeout(() => {
            resolve('data2');
        }, 1000);
    });

    // 展示数据2
    console.log(data2);
}

showData();

async function getData() {
    // 假装请求数据1
    var data1 = await new Promise((resolve) => {
        setTimeout(() => {
            resolve('data1');
        }, 1000);
    });

    // 假装请求数据2且此请求依赖数据1
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve('data2');
        }, 1000);
    });
}

getData().then((v) => {
    console.log(v);
});

15、手写一个 Ajax

AJAX: Asynchronous JavaScript and XML,是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助。简单地说,在不需要重新刷新页面的情况下,Ajax 通过异步请求加载后台数据,并在网页上呈现出来。常见运用场景有表单验证是否登入成功、百度搜索下拉框提示和快递单号查询等等。

GET请求
myButton.addEventListener('click',() => {
    var xhr = new XMLHttprequest()                                  //创建
    xhr.open('GET','/xxx?username=keduoc&password=123',true)        //初始化  true代表异步
    xhr.send()                                                      //发送
    xhr.onreadystatechange = () =>{                                 //监听
        if(xhr.readyState === 4){              //响应整体如果太大,分包到达,第一部分第二部分第四部分依次到达,故第一部分中的状态码200先到,而后整体都接收完,readystate才变为4.而之所以先判断4,是因为,只有接收完才能提取第二部分和第四部分
             console.log('请求响应都完毕了')
              if(xhr.status >=200 && xhr.status < 300){
                  console.log('说明请求成功了')
                  let string = xhr.responseText
                  let object = JSON.parse(string) 
                  console.log(object.note)
                }else if (xhr.status >= 400){
                   console.log('说明请求失败了')
                   }
           }
   }
}

POST请求
myButton.addEventListener('click',() => {
    var request = new XMLHttprequest()              //创建
    request.open('POST','/xxx',true)                //初始化  true代表异步
    request.send('username=keduoc&password=123')    //发送
    request.onreadystatechange = () =>{             //监听
        if(request.readyState === 4){               //响应整体如果太大,分包到达,第一部分第二部分第四部分依次到达,故第一部分中的状态码200先到,而后整体都接收完,readystate才变为4.而之所以先判断4,是因为,只有接收完才能提取第二部分和第四部分
             console.log('请求响应都完毕了')
              if(request.status >=200 && request.status < 300){
                  console.log('说明请求成功了')
                  let string = request.responseText
                  let object = JSON.parse(string) 
                  console.log(object.note)
                }else if (request.status >= 400){
                   console.log('说明请求失败了')
                   }
           }
   }
}

JS可以设置请求的四个部分:

第一部分:request.open('get','/xxx(路径)')

第二部分:request.setHeader('Content-Type','x-www-form-urlencoded')

第三部分:是个空行就不改了

第四部分:request.send('a=1&b=2')

JS可以获取响应的四个部分:

第一部分:request.status(状态码)/request.statusText(OK/NO)

第二部分:request.getResponseHeader('Content-Type')/request.getAllResponseHeaders()

第三部分:

第四部分:request.responseText

$.ajax()源码:

$.ajax({
  url:'test.do', 
  data:{id:123,name:'xiaoming'}, 
  type:'post', 
  dataType:'json', 
  success:function(data){
   alert(data);//弹窗 
   //TODO ........
  },
  error:function(data){
    alert(data);//弹窗
    //TODO ........
  }
 })

$.post() 与 $.ajax() 的区别

父子关系 :.post 底层由 .ajax 实现的.

.post源码:

post: function( url, data, callback, type ) {
    if ( jQuery.isFunction( data ) ) {
        callback = data;
        data = {};
    }

    return jQuery.ajax({
        type: "POST",
        url: url,
        data: data,
        success: callback,
        dataType: type
    });
},

16、闭包是什么

闭包的定义:「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。
在这里插入图片描述

闭包的作用:闭包常常用来「间接访问一个变量」。换句话说是,「隐藏一个变量」。

我们在写代码的时候,如果不用闭包,也可以直接用一个全局变量,但全局变量很容易被别人不小心篡改。所以我们不能让别人「直接访问」这个变量。怎么办呢?

用局部变量。

但是用局部变量别人又访问不到,怎么办?

暴露一个访问器(函数),让别人可以「间接访问」。

代码如下:

!function(){
  var lives = 50
  window.奖励一条命 = function(){
    lives += 1
  }
  window.死一条命 = function(){
    lives -= 1
  }
}()

在这里插入图片描述

这样,还剩几条命就不会被轻易篡改,而是需要用相应的函数才可以更改。

闭包经典应用

//给每个li绑定一个click事件,输出他们的顺序
var lis = document.getElementsByTagName('li');
var len = lis.length;

for(var i = 0; i < len; i++){
    !function(i){
        lis[i].addEventListener('click',function(){
            console.log(i)
        },false)
    }(i)
}

17、什么是立即执行函数?使用立即执行函数的目的是什么?

function(){...}() (function(){})()

立即执行函数的目的是:造出一个函数作用域,防止污染全局变量

18、这段代码里的 this 是什么?

  1. function() 里面的 this 就是 window
  2. function() 是 strict mode,this 就是 undefined
  3. a.b.c.function() 里面的 this 就是 a.b.c
  4. new F() 里面的 this 就是新生成的实例
  5. () => console.log(this) 里面 this 跟外面的 this 的值一模一样

19、JS 原型是什么?

举例

var a = [1,2,3]
只有0、1、2、length 4 个key
为什么可以 a.push(4) ,push 是哪来的?

a.__proto__ === Array.prototype

push 就是沿着 a.__proto__ 找到的,也就是 Array.prototype.push
Array.prototype 还有很多方法,如 join、pop、slice、splice
Array.prototype 就是 a 的原型(__proto__

20、JS 如何实现继承?

1.原型链

function Dialog(target) {
    this.target = target
}
Dialog.prototype.show = function() {
    console.log(this.target + ' show')
}
Dialog.prototype.hide = function() {
    console.log(this.target + ' hide')
}
var dialog = new Dialog('body')
dialog.show()

function Message(target, name) {
    Dialog.call(this, target)     //这句很重要  继承内部属性
    this.name = name
}
Message.prototype = Object.create(Dialog.prototype)   //这句更重要    继承方法
Message.prototype.success = function() {
    console.log(this.name + ' success' )
}

var msgBox = new Message('main', 'msg')
msgBox.show()
msgBox.success()

Dialog.call(this, target)的作用是: 执行函数 Dialog(target),执行的过程中里面遇到 this 换成当前传递的 this

Object.create(Dialog.prototype)的作用是:创建一个空对象,空对象的__proto__等于 Dialog.prototype

2、封装函数形式
继承 圣杯模式 雅虎库改进后

var inherit = (function (){
        var F = function (){};
        return function(Target,Origin){
            F.prototype = Origin.prototype;
            Target.prototype = new F();
            Target.prototype.constructor = Target     // constructor 属性返回对创建此对象的数组函数的引用。
            Target.prototype.uber = Object.prototype  // 最顶级的原型是object原型
        }
})()

3、extends 关键字
代码:

 class Animal{
      constructor(){
          this.body = '肉体'
      },
      move(){}
  }
  class Human extends Animal{
      constructor(name){
          super.move()
          this.name = name
      },
      useTools(){}
  }
  var frank = new Human()

21、如何实现深拷贝?

1)JSON 来深拷贝

缺点:JSON 不支持函数、引用、undefined、RegExp、Date……

var a = {…}
var b = JSON.parse( JSON.stringify(a) )

2)递归拷贝

 function clone(Obj) {
        var newObj;   
        if (Obj instanceof Array) {
            newObj = [];  // 创建一个空的数组
            var i = Obj.length;
            while (i--) {
                newObj[i] = clone(Obj[i]);
            }
            return newObj;
        } else if (Obj instanceof Object){
            newObj = {};  // 创建一个空对象
            for (var k in Obj) {  // 为这个对象添加新的属性
                newObj[k] = clone(Obj[k]);
            }
            return newObj;
        }else{
            return Obj;
        }
    }

22、如何实现数组去重

1)计数排序的逻辑(只能正整数)

数组中数字去重

var a = [4,2,5,6,3,4,5]
 var hashTab = {}
 for(let i=0; i<a.length;i++){
     if(a[i] in hashTab){
         // 什么也不做
     }else{
         hashTab[ a[i] ] = true
     }
 }
 //hashTab: {4: true, 2: true, 5: true, 6:true, 3: true}
 console.log(Object.keys(hashTab)) // ['4','2','5','6','3']

数组中多条对象去重

var oldArr = [
    {name:"zhang"},{name:"wang"},{name:"zhang"},
    {name:"li"},{name:"zhao"},{name:"li"}
];//原数据数组

var allArr = [];//新数组
for(var i=0;i<oldArr.length;i++){
  var flag = true;
  for(var j=0;j<allArr.length;j++){
    if(oldArr[i].name == allArr[j].name){
      flag = false;
    };
  }; 
  if(flag){
    allArr.push(oldArr[i]);
  };
};

2)Set 去重

var a = [4,2,5,6,3,4,5]
Array.form(new Set(a))

Set 返回值是一个Set对象;
Array.form() 将参数转化为数组。

23、如何用正则实现 string.trim() ?

 function trim(string){
     return string.replace(/^\s+|\s+$/g, '')
 }

开头有多个空格:^\s
多个空格接上结尾: |\s+$

24、ES 6 中的 class 了解吗?

作用:定义一个类。

1、类声明:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

2、类的方法:原型方法和静态方法

原型方法:将定义的方法 放在类的prototype上

class Rectangle {
    // constructor
    constructor(height, width) {
        this.height = height;
        this.width = width;
    }
    // Getter (下面的 get 可省略不写)
    get area() {
        return this.calcArea()
    }
    // Method
    calcArea() {
        return this.height * this.width;
    }
}
const square = new Rectangle(10, 10);

console.log(square.area);
// 100

静态方法:调用静态方法不需要实例化该类,但不能通过一个类实例调用静态方法。是将方法定义在这个类本身。

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }

    static distance(a, b) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;

        return Math.hypot(dx, dy);
    }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);

console.log(Point.distance(p1, p2));

3、类中的this:如果调用的对象没有“this”值,那么“this”值在被调用的函数内部将为 undefined。

class Animal { 
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

let obj = new Animal();
obj.speak(); // Animal {}
let speak = obj.speak;
speak(); // undefined

Animal.eat() // class Animal
let eat = Animal.eat;
eat(); // undefined

//如果我们使用传统的基于函数的类来编写上述代码,那么基于调用该函数的“this”值将发生自动装箱。

function Animal() { }

Animal.prototype.speak = function() {
  return this;
}

Animal.eat = function() {
  return this;
}

let obj = new Animal();
let speak = obj.speak;
speak(); // global object

let eat = Animal.eat;
eat(); // global object

4、extends 创建子类

5、super 调用对象的父对象上的函数。

class Cat { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(this.name + ' roars.');
  }
}

var a = new Lion('jack')
a.speak()
//jack makes a noise.
//jack roars.
发布了4 篇原创文章 · 获赞 0 · 访问量 119

猜你喜欢

转载自blog.csdn.net/weixin_43915673/article/details/104716990
今日推荐