原生面试题系列02

11、原型和原型链

1)、原型:

每个函数都会有一个属性prototype。这个属性就是原型属性。JavaScript在实现面向对象时,会经常使用原型。每个对象(实例)的有一个属性( __ proto __)指向构造函数的prototype属性(prototype指向的内存区域)。prototype属性里保存着所有对象(实例)共享的属性和方法。

2)、原型链:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的 __ proto __ 隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的 __ proto __中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

12、作用域和作用域链

原生js面试题:作用域和作用域链,let声明的全局变量不是window对象的属性_jiang7701037的博客-CSDN博客_let不影响作用域链

作用域,就是变量起作用的区域(范围)。或者说,js代码执行时,查找变量的范围。

作用域链是指:当js编译器在寻找变量时,先在最近的作用域(花括号)里找,如果找不到,则朝上一级作用域(花括号)里找,依次类推,直到找到或者找不到为止。这就是作用域链。

13、Ajax的步骤与封装 AJAX中的200和4分别是什么意思

1)、AJAX的步骤:

ajax的流程,readyState和status的意思
​
1、创建XMLHttpRequest
​
    let xhr = new XMLHttpRequest() 
​
2、设置(请求方式,请求路径,请求参数)
​
    xhr.open("get", "regSave.php?username=jzm&userpass=123", true) 
​
3、设置回调函数(后端有响应时,调用的回调函数) 
​
    xhr.onreadystatechange = function() {
​
        if (xhr.readyState == 4 && xhr.status == 200) {
              xhr.responseText //后端响应的内容,如:php中的echo 后面跟的内容
        }
    } 
​
4、发送
    xhr.send(); 
​
//readyState:请求响应的状态(请求响应进行到哪一步了)
​
//status:响应结果的描述,是个状态码(数字)
​

2)、封装ajax的代码:

​
function ajax2110UseObj(obj){
​
    let defaultObj = {
        method:"get",
        url:"#",
        params:"",
        callback:null,
        isAsync:true
    }
​
    for(let key in defaultObj){
        // 把obj里没有传入的属性使用defaultObj的对应属性。
        if(obj[key]==undefined){
            obj[key]=defaultObj[key];
        }
    }
​
    // 1、创建XMLHttpRequest对象
    let xhr = new XMLHttpRequest();
​
    // 2、设置请求相关信息
    let urlAndParams = obj.url;
    if(obj.method.toLowerCase()=="get"){
        urlAndParams += "?"+obj.params
    }
​
    xhr.open(obj.method,urlAndParams,obj.isAsync);
​
    // 3、设置回调函数(后端响应时,调用的函数)
    xhr.onreadystatechange = function(){
        if(xhr.readyState==4 && xhr.status==200){            
            obj.callback && obj.callback(xhr.responseText);
        }
    }
​
    if(obj.method.toLowerCase()=="get"){
        // 4、发送请求
        xhr.send();
    }else if(obj.method.toLowerCase()=="post"){
        // 如果是post方式,必须设置请求头。
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
        xhr.send(obj.params);
    }
​
}
​

3)、200和4分别是什么意思

readyState属性:表示ajax从请求到响应过程中的状态,即:请求响应过程中进行到了哪一步?readyState的取值是0 ---- 4。

0:表示刚创建好对象XMLHttpRequest

1:open函数调用完毕后,

2:表示后端接收到了响应

3:表示后端正在处理

4:表示后端处理完毕(即:请求响应的过程结束了)

readyState==4:表示请求响应的过程完毕

status属性: 这是表示http的响应状态码。200表示执行成功。关于其它HTTP状态码,可以查看文章:

HTTP请求响应系列02_响应报文的详解_jiang7701037的博客-CSDN博客

14、深浅拷贝 区别以及如何进行深拷贝

面试题:深拷贝和浅拷贝(超级详细,有内存图)_jiang7701037的博客-CSDN博客_深拷贝和浅拷贝

场景:

说深拷贝和浅拷贝,特指引用类型。

区别:

深拷贝: 把引用类型的地址及其它的数据都拷贝一份

浅拷贝: 只拷贝了引用类型的地址

如何进行深拷贝:

深拷贝的思路:

创建空对象,循环原对象的每个键,一一 赋值给空对象,并使用递归的方式,把对象属性也进行复制,以下为示例代码:

​
// 功能:封装一个深拷贝的函数
// 参数:被拷贝的对象
// 返回值:拷贝的对象
​
function copyObj(obj){
    let newObj ={};
    for(let key in obj){        
        if(typeof obj[key] == "object"){ //如果说当前属性是对象的话,那么再做深拷贝
            newObj[key] = copyObj(obj[key]);
        }else{
            newObj[key] = obj[key];
        }
    }
    return newObj;
}
​
var obj1= {
    name:"张三疯",
    sex:"男",
    address:{
        province:"陕西",
        city:"西安"
    }
}
​
let obj2 = copyObj(obj1);

面试题:深拷贝和浅拷贝(超级详细,有内存图)_jiang7701037的博客-CSDN博客_深拷贝和浅拷贝

15、promise都有哪几种状态 其执行状态

概述:

Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,可以获取异步操作的消息

作用:

(1)、避免回调地狱的问题

(2)、Promise对象提供了简洁的API,使得控制异步操作更加容易

Promise有三种状态:

pendding :正在进行中,

rejected :失败,

resolved : 成功

基础用法:

new Promise(function(resolve,reject){

异步代码

})

16、数组去重的方法

①利用数组indexof方法

   function unique(arr) {
        var arr1 = [];
        for (var i = 0; i < arr.length; i++) {
            if (arr1.indexOf(arr[i]) == -1) {
                arr1.push(arr[i]);
            }
        }
        return arr1;
    }
​
    console.log(unique([1,1,2,2,3,3,3,4,5,6,6,6,7]));//1,2,3,4,5,6,7

②ES6的Set

function unique(arr){
    return [...new Set(arr)]
}
​
console.log(unique([1,2,1,2,2,3,2,1]));

数组去重的方法比较多,大家可以自行再思考

17、js如何创建数组,js数组都有哪些方法?

1、有两种创建方式:

①字面量创建: var arr=[];

②构造函数创建: var arr1=new Array();

2、js数组的方法:

push 尾增

pop 尾删

unshift 头增

shift 头删

concat 数组拼接

join 数组转字符串

reverse 逆序

sort 按字符串UniCode码排序

map 对数组的每个元素做某个处理,参数是回调函数,并且有返回值

slice 复制

indexOf 查找数组中的元素,找到返回该元素下标, 没找到返回-1

splice 截取

filter 过滤

every 对数组中的每一项进行判断,若都符合则返回true,否则返回false

some 对数组中的每一项进行判断,若都不符合则返回false,否则返回true

reduce:将数组所有数值进行叠加返回

forEach 对数组的每个元素做某个处理,参数是回调函数

18、同一个数组,同样的限制条件,map和filter find返回值有什么区别

相同点:都不会改变原数组

不同点:

map返回值是一个新的数组,新数组中的元素为原始数组中的元素调用函数处理后的值。

find返回值:方法返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。返回值不是数组!

const array1 = [5, 12, 8, 130, 44];
​
const found = array1.find(element => element > 10);
​
console.log(found);//12
​

filter返回值:返回一个新数组 是原数组中符合条件的所有元素。

19、延时器(宏任务微任务)

javascript的事件循环(event loop)_jiang7701037的博客-CSDN博客

1)、宏任务(macrotask )

宏任务一般包括: setTimeout,setInterval,I/O 操作(包括AJAX请求)。

2)、微任务(microtask )

微任务一般包括:promise.then() 里的操作

20、闭包 什么情况下会使用闭包

概念:定义在一个函数内部的函数,并且这个内部函数能够访问到外层函数中定义的变量

作用:

①让外部访问函数内部变量成为可能

②局部变量会常驻在内存中

③可以避免使用全局便变量,防止全局变量污染

缺点:

会造成内存泄露(内存空间长期被占用,而不被释放)

场景:

1)、只有一个方法的对象

因为闭包允许将函数与其所操作的某些数据(环境)关联起来。这显然类似于面向对象编程。在面向对象编程中,对象允许我们将某些数据(对象的属性)与一个或者多个方法相关联。

因此,通常你使用只有一个方法的对象的地方,都可以使用闭包。

示例:

//面向对象的类
// class Person{
//     constructor(){
//         this.name = "陈琳"
//     }
​
//     eat(){
//         console.log(this.name+"在吃,天在看……");
//     }
// }
​
// let p1 = new Person();
​
// p1.eat();
​
//使用闭包
function person(str){
    var name = str;
    return function(){
        console.log(name+"在吃,天在看……");
    }
}
​
let eat = person("陈琳");
eat();
​

2)、如果某些数据,只希望某些函数操作使用

3)、用闭包模拟私有方法

编程语言中,比如 Java,是支持将方法声明为私有的,即它们只能被同一个类中的其它方法所调用。

而 JavaScript 没有这种原生支持,但我们可以使用闭包来模拟私有方法。私有方法不仅仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱了代码的公共接口部分

function person(str){
    var name = str;
    var age = 20;
    
    function setAge(transAge){
        fn2();
        age = transAge;
    }
​
    function getAge(){
        fn2();
        return age;
    }    
​
    function fn2(){
        console.log("fn2");
    }
​
    return {
        setAge:setAge,
        getAge:getAge
    }   
}
​
let p = person("陈琳");
p.setAge(18);
console.log(p.getAge());
​
p.fn2();
上一篇:原生js中的ajax请求


下一篇:前后端数据交互(二)——原生 ajax 请求详解