JavaScript面试题

堆和栈的区别主要有五大点,分别是:

1、申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;

2、申请大小的不同。栈获得的空间较小,而堆获得的空间较大;

3、申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;

4、存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;

5、底层不同。栈是连续的空间,而堆是不连续的空间。

事件委托的好处

1、可以在批量子元素实现功能时,由父元素的事件体实现子元素功能。降低代码冗余,提高程序效率

2、可以为将来添加的元素提前绑定事件

arguments

1、arrguments:函数体内置对象,作用在函数体内。是一个伪数组(只能访问元素和length属性,其他API不能操作),保存着所有的实参

2、arrguments.callee:代表函数体本身

原型对象

1、原型对象是函数对象的一个属性-prototype,它保存着所有实例对象共享的属性和方法

2、当一个实例对象修改了同名的原型对象属性时,是不能实现的,等价于实例对象自己创建了一个同名属性

3、为什么实例对象可以访问原型对象的属性和方法:实例对象可以访问自己new出来的属性和方法,实例对象在创建时会生成一个__proto__属性,它指向原型对象的所有属性和方法

apply和call(多态)

1、都是修改this指向的

apply:函数对象:apply(被修改this指向的实例化对象,[原函数的参数1,参数2])

call:函数对象:call(被修改this指向的实例化对象,原函数的参数1,参数2)

apply,call,bind的异同

1、都是用来修改this指向的

2、apply和call是用来修饰有名函数,bind是用来修饰匿名函数

3、apply和call会直接调用该方法,bind会生成一个新的函数对象

4、apply的第二个参数必须是数组,call和bind第二个参数用逗号隔开

匿名函数

没有名字的函数

1、把一个函数当做一个变量赋值

let fun = function(){alert("亲,我来自无名函数");

}

2、回调函数,一个被当作函数参数的函数

setInterval(function(){

    ​    console.log("heihei");

},1000);

3、作为函数的返回值

function f1(){// let f2 = function(){// }// return f2;return function(){}

}

自运行

针对匿名函数,当匿名函数被定义时,可以被直接调用

//b.官方推荐

(function(){

    ​    console.log("嘿嘿嘿");

}());

闭包

概念:函数嵌套函数,被嵌套的函数称为闭包函数

闭包的作用:可以在函数的外部使用该函数内部的变量及柯里化函数

高级理解:1、类的公有和私有属性

2、柯里化函数

闭包的实现:一个函数内部定义一个变量,嵌套子函数,在子函数中操作这个变量,将子函数作为父函数的返回值,通过定义一个全局变量,和父函数的返回值(子函数)进行绑定,从而延长局部变量的生命周期

闭包的缺陷:延长了局部变量的生命周期

打破了原有的垃圾回收机制,大量使用闭包会导致内存泄露

function f1(){var count = 0;var f2 = function(){++count;return count;}return f2;

}

// f = f1() = f2  //绑定

let f = f1();

console.log(f());

console.log(f());

console.log(f());

//变形写法

function f1(){var count = 0;return function(){return ++count;}

}

let f = f1();

console.log(f());

console.log(f());

console.log(f());

柯里化函数:一个拥有一个参数,且返回值为一个函数的函数

作用:柯里化实际上是把简单的问题复杂化了,但是复杂的同时使得函数有更多的自由度

而这种对函数参数的自由处理,正式柯里化的核心

柯里化本质是降低通用性,提高适用性

// 柯里化思想

function regChecked(reg){return function(str){return reg.test(str);}

}

//1.测试用户名

// 创建工具函数

let checkedUserName = regChecked(/^\D\w{5,17}$/);

console.log(checkedUserName("laowang"));

console.log(checkedUserName("111"));

console.log(checkedUserName("hahahahaah"));



//2.测试密码

//创建工具函数

let checkedUserPwd = regChecked(/^.{6,}$/);

console.log(checkedUserPwd("123"));

console.log(checkedUserPwd("454646"));

console.log(checkedUserPwd("hahahahaah"));

this的作用

概念:this是函数的内置对象,只能出现在函数的作用域内

1、作用于事件体函数时:表示触发该事件的元素

2、作用于构造函数时:表示new出来的对象

3、作用于普通函数(除了事件体函数和构造函数)时:表示调用该函数的对象(指向window)

4、作用于箭头函数时:代表其父元素的前缀

继承

1、子类吸收父类已有的属性和方法(拿来直接用),大大提高了代码的复用性

原型继承:依赖原型对象实现继承

缺陷:

1、一定要先实现继承关系,再为子类添加属性和方法

2、一旦继承关系实现,就无法修改原型对象的this指向

3、无法在子类对象构造时,初始化由父类派生的属性

unction Animal(name){this.name = name;

}

Animal.prototype.eat = function(){

​    console.log("Animal eat");

}

function Human(id){this.id = id;

}

Human.prototype = new Animal("老王");

Human.prototype.makeTools = function(){

​    console.log("Human makeTools");

}

2、借用构造方法继承(apply和call):

作用:可以在子类对象构造时,初始化由父类派生给子类的属性

缺陷:无法实现原型对象的继承

3、混合继承:1、通过apply和call实现属性的继承

​ 2、通过原型对象继承,实现原型对象的属性和方法继承

4、ES6继承:

使用extends关键字:子类 extends 父类

super:借用父类的构造方法

typeof和intanceof的区别

1、都是用来判断数据类型的

2、typeof用来判断基本数据类型,判断引用数据类型时都会返回object

3、intanceof用来判断引用类型,并且满足兼容性规则。返回布尔值

值传递和引用传递

1、值传递:内置基本类型作为实参,单向传递,只能由实参改变形参,反之不行

2、引用传递:引用数据类型作为实参,双向传递,形参可以改变实参

深拷贝和浅拷贝

深浅拷贝只针对于引用类型

1、浅拷贝:只拷贝内容,不开辟新空间,两个对象共用一块空间地址

2、深拷贝:即拷贝数值,也开辟新空间,每个对象拥有独立的空间地址

本地存储

1、localstorage:本地永久存储,将数据存储在本地磁盘中,除非删除,否则一直存在

2、sessionstorage:本地临时存储,将数据存放在浏览器客户端内,页面关机就消失

getItem():获取本地存储数据

setItem():添加本地存储

removeItem():删除本地存储

clear():删除所有本地存储

key(index):返回列表对应下标的key值

cookie和localstorage、sessionstorage的区别

1、存储方式:

cookie的临时会话存储在浏览器中,会话结束就会消失

长生命周期的cookie存在本地磁盘中,到期或者删除会消失

localstorage是本地永久存储,存储在本地磁盘里,除非删除,否则一直存在

sessionstorage临时存储,存储在浏览器客户端中,页面关闭就会消失

2、储存大小:

cookie存储大小一般为4KB

本地存储大小一般为5mb

3、与服务器端的通信方:

cookie每次都携带在http头中,大量使用会影响性能

本地存储不参与和服务器的通信

4、易用性:

cookie的原生api不友好

本地存储的原生api可以接受,还可以再次封装来对Object和Array更好的支持

Object.defineproperty及双向绑定的原理

1、以前都是dom驱动,vue都是数据驱动

2、vue数据驱动,双向绑定原理,object.defineproperty

3、object.defineproperty是ES5的一个函数,为对象添加属性

<html lang="en">


    <head>
        <meta charset="UTF-8">
    
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
    
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
        <title>Document</title>
    
    </head>
    
    <body>
    
        <input type="text" value="">
    
    </body>



</html>

<script>


    let data = {
    
    }
    
    let oInput = document.querySelector("input");
    
    Object.defineProperty(data, "content", {get: function () {return oInput.value;},set: function (v) {
    
                ​      oInput.value = v;}
    
    });
    data.content = 9999;

</script>

proxy

1、语法:let proxy = new Proxy(被代理的目标对象,修饰符)

let data = {

    ​    name:"老王",

    ​    age:18,fun:function(){

        ​      console.log(this);},

            ​    hobby:["唱","跳","rap","你干嘛"]

}

let proxy = new Proxy(data,{//set(目标对象,属性名,属性值,[代理对象])set:function(target,property,value){

    ​      console.log("set");// target[property] = value;

    ​      Reflect.set(target,property,value);},//get(目标对象,属性名,[代理对象])get:function(target,property){

            ​      console.log("get");//return target[property];return Reflect.get(target,property);}

});

// proxy.name = "老六";

// console.log(proxy.name);


// proxy.age = 88;

// console.log(proxy.age);


data.fun();

proxy.fun();

为什么要使用proxy替代Object.defineProperty

1、proxy可以对一个对象的所有属性添加get和set,而Object.defineProperty则需

要把每一个对象的属性都写出来

2、Object.defineProperty没有深度遍历,如果修改数组元素则不会触发get和set,但proxy可以

hasOwnProperty

1、作用:只遍历自身属性,不遍历原型链上的属性

let data = {

    ​    name:"蔡徐坤",

    ​    age:24

}


Object.prototype.a = 666;


//console.log(data.a);


//需求:只需要遍历自身的属性而不考虑原型链的属性?

//hasOwnProperty:只遍历自身的属性,不去遍历原型链上的属性

for(let index in data){//对象.hasOwnProperty(属性值):是自身的属性返回true,是原型上的属性//返回falseif(data.hasOwnProperty(index)){

        ​      console.log(data[index]);}

}

Ajax

1、什么是Ajax

Ajax是一种网页异步交互技术。传统的网页需要更新内容时,必须要重载整个页面。通过Ajax异步交互技术,当需要更新页面局部内容时,无需重载整个页面就可以实现。前端通过Ajax与服务器少量的数据交换,可以使网页实现异步更新

2、为什么要使用Ajax

a.更自然,流畅的用户体验,对用户的操作及时响应

b.在不中断用户操作的情况下与web服务器通信

c.更灵敏的响应用户访问,实现接近于桌面应用程序的交互效果

d.通过局部更新页面降低网络流量,提高网络的使用效率

异步和同步

1、JS是单线程语言,为了解决同时出现多个任务引入了同步与异步技术

2、所有代码都消耗执行时间,异步代码有等待时间

3、同步代码按照顺序一步一步执行,必须前一步执行完毕,后一步才能继续执行

4、异步代码在执行时,如果遇到需要消耗等待时间的代码,则会先跳过该代码,先执行后续代码,直至代码消耗完等待时间再去执行

注意事项:优先执行同步代码,只有同步代码遵循自上而下的执行顺序

只要消耗等待时间的代码都是异步代码

5、常见的异步代码:a.定时器的回调函数

b.事件体

c.发请求和接相应(围绕着Ajax)

事件轮循机制

所有代码最终都要通过主线程编译,同步代码储存在执行栈,异步代码储存在任务队列

1、先执行栈的同步代码

2、异步模块有消耗完等待时间时,会告知主线程,准备进入执行状态

3、主线程等所有同步代码执行完成后,将把等待时间消耗完成的代码拉入主线程执行

异步代码又分为宏任务和微任务:

I/O、UI交互事件、setImmediate(node环境)

微任务大概包括:new promise().then(回调)、

MutationObserver(html5新特新)、Object.observe(已废弃)、

process.nextTick(node环境)

执行异步代码时,有微则先微,无微则宏

4、重复以上三步

Ajax步骤

1、创建Ajax核心对象–XMLHttpRequest

2、open

3、send

4、onreadystatechenage

5、返回信息—responseText

//1.掏手机--->创建ajax核心XMLHttpRequest对象

let xhr = new XMLHttpRequest();

//2.拨号-=->open

// xhr.open("请求的方式get/post","服务器文件地址",是否异步);

xhr.open("get","ajax.txt",true);

//3.发射--->send

xhr.send();

//4.等onreadystatechange事件

//异步

xhr.onreadystatechange = function(){// 听见嘟嘟嘟嘟~~~// 对方接通电话if(xhr.status == 200 && xhr.readyState == 4){//5.返回给你信息//responseText服务器根据请求返回给前端的信息fun(xhr.responseText);}

}

function fun(resText){

    ​    console.log(resText);

}

Ajax的属性

1、readystate:是xhr对象的属性,发请求和接响应过程中的状态码

0:刚创建完xhr对象

1:调用完open方法准备发送

2:调用了send方法,将请求发送出去

3:数据发到了服务器

4:服务器接收完成解析返回响应

get和post的异同

1、post不能在url携带请求参数

2、post必须在open和send之间设置请求头

3、将请求参数写在send中

接口

1、什么是接口:接口的本质就是服务器文件地址0

2、接口四要素:a.接口地址

b.接口请求类型

c.请求参数

d.返回的数据格式

promise

1、什么是promise

promise是一个对象,该对象是一种异步处理机制。异步代码是无法决定执行顺序,当我们需要将异步代码按照一定顺序执行时,会使用回调函数的嵌套来解决。但回调函数的嵌套会形成回调地狱,为了解决回调地狱问题(其实是为了优化异步代码必须遵循先后顺序的写法),可以将函数调用的写法改为平级调用。

2、promise的功能

可以让回调函数不从主函数的参数位置传进来

3、promise的参数

promise有两个参数success和failed,这两个参数依然是回调函数。success是用来接收请求成功时的响应,failed是用来接收请求失败时的响应,可以不写

all和race

//1、all:一次发送多个请求,必须保证所有的请求都收到才会渲染页面

Promise.all([p1,p2,p3]).then(function(resText){

    ​    console.log(resText);

});

//2、race:一个页面的渲染,很多服务器都有相同的接口,为了效率一次可以发送多个请求,那个先返回就使用那个

Promise.race([p1,p2,p3]).then(function(resText){

    ​    console.log(resText);

});

async和await

async是修饰函数的关键字,await必须搭配async一起使用。async 函数返回的是一个promise 对象,await 表示等一下,代码就暂停到这里,不再向下执行了,它等什么呢?等后面的promise对象执行完毕,然后拿到promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行

async是修饰函数的关键字,async和await基本是组合使用的,async用来声明一个异步方法,返回的是一个promise对象,如果要获取到对应的返回值,就需要使用.then方法

await只能在async方面的里面使用,让后面的执行语句或方法要等待当前await方法的结果后才能再执行。

跨域

跨域:A网站的页面去访问B网站的服务器文件

如果只需要知道某台电脑的ip,

以及文件名,难道就可以访问那台电脑所有内容?

同源策略:浏览器的一种安全机制,只能访问

a.同ip

b.同端口

c.同协议

的文件

实际需求中,很多地方就得跨域访问

如访问百度的搜索引擎,导航,天气预报,人工智能客服

跨域的解决方案

前端:jsonp

jsonp就是个名字,(叫啥都行),它是前端跨域的一种技巧(没有新语法),

可以实现跨域访问

怎么实现:

1.src属性自带跨域

2.script标签也是有src属性的

3.srcipt+src也可以跨域

4.前端写函数定义

后端模拟函数调用,通过参数返回响应的

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值