Javascript学习笔记面试(二)js基础部分

1、变量的类型和计算

1.变量类型

//值类型
let a = 200;
let b = a;
a = 100;
console.log(a, b)

// 引用类型
let a = { age: 24 };
let b = a;
b.age = 25;
console.log(a, b);
值类型和引用类型的区别?

值类型,值类型的复制就是复制栈里的value
引用类型的复制复制的是堆的引用内存地址css

为何?

值类型的占据内存比较小,引用类型占据的内存可能会很是大,不利于复制,从CPU和性能考虑把引用类型和值类型的复制的方式给分离出来。(js引擎)html

哪些是值类型?哪些是引用类型?
let a;// undefined
const b = "string";
const c = false;
const n = 100;
const s = Symbol('s');
const obj = { age: 24 };
const arr = ["1", "2", "3"];

const n = null; // 特殊的引用类型,指针指向的是空地址

// 特殊引用类型 不用于存储数据,因此没有拷贝,复制函数之说
function fn() { }
typeOf 类型判断
全部的值类型,函数
引用类型只能到Object
手写深拷贝

重点1:初始化result
重点2:使用递归webpack

obj1 = {
            name: "胡子银",
            level: "p0"
        };

        function deepClone(obj = {}) {
            if (typeof obj !== 'object' || typeof obj == null) {
                return obj;
            }
            // 初始化返回结果
            let result;
            if (obj instanceof Array) {
                result = []

            } else {
                result = {}
            }
            // 开始拷贝
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    // 保证key 不是原型的属性
                    // 递归调用
                    result[key] = deepClone(obj[key]);
                }
            }
            return result;
        }

2.变量计算

字符串拼接
const a =100+10 // 110
const b = 100 +'10' // '10010'
const c= true + '10' // 'true10'
==运算符
100 == '100' // true
0 == '' // true
0 == false // true
false =='' // true
null == undefined // true

总结: 除了null == 其余都用===ios

if语句和逻辑运算

truely 变量与 falsely 变量 两次取反es6

image.png

2、原型和原型链

面向对象

类的继承:extends super 重写web

隐式原型 与 显式原型

instanceof 是否是它构建的。父类。Object是全部的父类面试

Student.__proto__ === People.ProtoType // true

隐式原型 :Student.proto
显式原型:People.ProtoTypeajax

image.png

每一个class都有显式原型,每一个实例都有隐式原型,实例的隐式原型指向类的显式原型。json

原型链

image.png

instanceOfaxios

3、做用域和闭包

this 在不一样场景下,如何取值?
手写bind函数
闭包在实际开发场景中的应用
什么是做用域?

变量的合法使用范围。框里面的均可以。

做用域:

全局做用域

函数做用域

块级做用域 let const {}

什么是闭包?闭包会被做用到哪里?

做用域应用的特殊表现,有两种状况

  • 函数做为参数被传递。
  • 函数做为返回值被返回。

总之,函数定义的地方和执行的地方是不同的。

闭包:自由变量在函数定义的地方向上级做用域查找。而不是在执行的地方。

// 函数做为返回值
function createFun() {
    const a = 100;
    return function () {
        console.log(100);
    }
}

const fn = createFun();

const a = 200;
fn();
// 函数做为参数被传递
const a = 100;
function param() {
    console.log(a);
};

function close(param) {
    const a = 200;
    param();
};

// const clo = new close(param);

close(param);
this的几种赋值状况

函数在执行的时候决定。

箭头函数 ==> 取的是上级做用域的值

bind call 的区别

function fn() {
    console.log(this);
}
const fnbind = fn.bind({ x: 200 },10,20,30);
fn();
fn.call({ x: 100 });
fnbind()

image.png

做用域相关的面试题
this的使用场景,console.log(this)

一、普通函数被调用 // window

二、做为对象方法 指向对象

三、bind,call,apply 把this的指向做为参数传递进去。(传进去的就是this)

四、箭头函数 this指向上一层做用域

五、在class中调用
手写bind函数
JavaScript中的 Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组
Function.prototype.bind = function () {
    const args = Array.prototype.slice.call(arguments);
    // 获取数组的第一项
    const t = args.shift();
    //此处this是fn1.bind()中的fn1
    const self = this;
    return function () {
        return self.apply(t, args);
    }
}
闭包中的应用

闭包: 自由变量在函数定义的地方向上级做用域查找。而不是在执行的地方。

闭包隐藏数据,只提供api,闭包中的数据,被隐藏,不被外界访问。

建立缓存,set,get,调用get方法取到的变量是,而不是

image.png

let构成了块级做用域
image.png

4、异步

基础
const imgUrl = "0000";
        function loadImg(src) {
            return new Promise((resolve, reject) => {

                const img = document.createElement('img');

                img.onload = () => {
                    return resolve(img);
                }
                img.onerror = () => {
                    return reject(new Error("图片加载失败"));
                }
                img.src = img;

            })
        }
        
loadImg(url).then((img) => {
            console.log(img.width);
            return img;

        }).then((img) => {
            console.log(img.height);
        })
进阶

事件轮训,事件循环

js是单线程,异步要基于回调实现,event Loop就是根据异步回调的实现原理

js是怎样执行的?

image.png

image.png

call Stack:调用栈 用完就清空

web apis:如setTimeout dom bom等

callback queue:回调函数队列

event loop:

总结:
同步代码,一行一行放在Call Stack执行

遇到异步,会先“记录”下,等待时机(定时、网络请求等);

时机到了,就移到Callback Queue

如Call Stack为空(即同步代码执行完成)Event Loop开始工做

轮询查找Callback Queue,若有则移到Call Stack 执行

而后继续轮询查找

dom事件也是基于Event Loop。

Promise

then 正常返回resolved ,里面有报错则返回rejected

catch 正常返回resolved,里面有报错则返回rejected

总结:

三种状态,状态和表现

then和catch对状态的影响(重要)

then和catch的链式调用(常考) 只要是没报错,就是resolved。

async await

异步回调

promise也是基于回调。async-await完全消灭了回调。

async和promise的关系

image.png

- 执行async函数,返回的是Promise对象

- await至关于Promise的then (假如直接返回的数据,至关于 Promise.resolve(400))

- try...catch可捕获异常,代替了Promise的catch

async await是语法糖 异步的本质仍是回调函数

仍是基于回调函数,仍是基于event Loop

for ...of

for...in(以及forEach for)是常规的同步遍历 ????

for...of 经常使用于异步遍历?????

宏任务与微任务

宏任务与微任务

  • 宏任务:setTimeout,setInterval,Ajax,DOM事件
  • 微任务:Promise,async/await
  • 微任务执行的时间要比宏任务执行的时间要早。

为何微任务比宏任务的执行时间要早?

event Loop 与 DOM事件 渲染。js是单线程的。也就是说event Loop与Dom渲染共用同一个线程。

宏任务在DOM渲染后触发,如setTimeout();

微任务,在DOM渲染后,如setTimeout();

image.png

为何宏任务在DOM渲染后触发,微任务在DOM渲染前触发?

宏任务与微任务的根本区别

从event Loop解释为何微任务比宏任务的执行时间早。

微任务是浏览器规定的

宏任务是es6规定的

存放的地方不同。

总结:

5、JS-WEB-API

JS = ECMA (ECMA262标准)+DOM(w3c) +BOM (w3c)

W3C规定web-api,css,html,网络请求的东西还挺多的。

5.1DOM

document object model

题目:

DOM是哪一种数据结构
DOM操做的经常使用API
attr和property的区别
一次性插入多个DOM节点,考虑性能

dom的本质

dom节点的操做

const div1 = document.getElementById("app1"); // 
const div2 = document.getElementsByClassName("appclass");
    
const divList = document.getElementsByTagName("div"); // list
const pList = document.querySelectorAll("p"); // 

console.log("div1:", div1);
console.log("div2", div2);
console.log("divList:", divList);
console.log("pList:", pList);

// property 形式 修改属性值
console.log(pList[1].style.width);
console.log(pList[1]);

// attribute 形式 修改属性
pList[1].setAttribute("data-name", "imook");
console.log(pList[1].getAttribute("data-name"));
pList[1].setAttribute("style", "font-size:50px");

打印出来的结果对比,直接获取的dom节点,list的会有属性
image.png

dom 结构操做

DOM性能

  • DOM操做很是昂贵,应该避免常常对DOM元素进行操做。
  • 对dom查询作缓存。
  • 将频繁操做改成一次性操做
const listNode = document.getElementById("app1");
const flagNode = document.createElement("ul");

for (let i = 0; i <= 5; i++) {
    const li = document.createElement("li");
    li.innerHTML = "innerHtml";
    flagNode.appendChild(li);
};

listNode.appendChild(flagNode);

5.2 BOM

题目

如何识别浏览器的类型?

ua

分析拆解url的各个部分。
// navigator
console.log(navigator.userAgent); // ua检查方案

// screen
console.log(screen.width);

// location
console.log(location.href); // 整个网址
console.log(location.host) // 域名
console.log(location.search);  // 
console.log(location.hash); // 哈希 #
console.log(location.pathname); // 

// history
history.back();
history.forward();

5.3 事件 事件绑定和事件冒泡

通用的事件绑定函数

<button id="btn1">点击</button>
<script>
    var btn = document.getElementById("btn1");

    function bindEvent(ele, type, fn) {
        ele.addEventListener(type, fn);
    };

    btn.bindEvent("click", e => {
        // 阻止默认行为
        e.proventDefault();
        // e.target
        console.log(e.target);
        console.log("事件绑定");
    })
</script>

事件冒泡

事件代理

把事件绑定到父元素上,点击子元素,弹出子元素的interhtml

代码简洁,减小浏览器的内存使用,可是不要滥用。

5.4 AJAX

GET

const xhr = new XMLHttpRequest();

xhr.open("GET", "./data.json", true);

xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(JSON.parse(xhr.responseText));
            alert(xhr.responseText);
        } else {
            console.log(xhr.responseText);
        }
    }
}
xhr.send(null);

POST

const xhr = new XMLHttpRequest();

xhr.open("POST", "./login", true);

xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            console.log(JSON.parse(xhr.responseText));
            alert(xhr.responseText);
        } else {
            console.log(xhr.responseText);
        }
    }
}
const postData = {
    "name": "狂徒张三"
}
xhr.send(JSON.stringify(postData));

image.png

image.png

301 永久重定向
302 临时重定向
304 资源有,重复,浏览器用本身的。事关性能优化
404 地址错了
403 没有权限

浏览器的同源策略

什么是跨域(同源策略)?
JSONP
CORS(服务端支持)

image.png

image.png

image.png

image.png

image.png

jsonp的主要内容有两点:
一、script能够跨域
二、服务器拿到url能够动态的返回一些内容

cors
是服务端设置请求头,容许哪些进行访问。

实际项目中ajax的经常使用插件

jqyery.ajax()

fetch()

axios
xmlhttprequest

5.5sessionStorage与localStorage的区别

题目:描述cookie localStorage sessionStorage 的区别

  • cookie
cookie的价值不在于本地存储,而在于与服务端的通讯。是被借用来做为本地存储的工具。因为每次请求都须要带着cookie,因此会增长请求的数据量,并且cookie的最大的存储空间是4kb,只能经过document.cookie来修改。过于简陋。

修改的方式:相同的key,覆盖,不一样的key,追加
  • sessionStorage与localStorage
localStorage数据会永久存储,除非代码或者手动删除

sessionStorage数据只存在于当前会话,当浏览器关闭就清空

六、HTTP

6.1 http的几个面试题

常见的状态码:
301 永久重定向
302 临时重定向,
举例1:在百度检索了一个css教程,hover上去的连接点击之后,先是访问百度的url而后浏览器的location再跳转到真正的目的连接地址、。
举例2:还有短链
304:浏览器已经请求过了,可使用本地的,本地的没过时
403:没权限
404:地址错误
5 **:服务端

关于协议和规范:就是一个约定和规范

6.2 http method

传统method

get
post

如今的method

get 查
post 建立新的
patch
delete

restful API
  • 一种新的API设计方法(早已推广使用)
  • 传统API设计:把每一个url当作一个功能
  • Reatful API设计:把每一个url当作一个惟一的资源标识

尽可能不要使用参数,使用method做为类型
image.png

image.png

6.3 http 常见headers

image.png

Request Headers

image.png

image.png

image.png

Request Headers

image.png

image.png

缓存相关的Headers

image.png

6.4 http为何须要缓存?

关于缓存的介绍

网络请求加载比较慢,cpu计算比较快。性能优化的主要瓶颈就在于网络请求,当部分不须要被重复请求的资源被缓存,就能够减小http请求,从而优化性能。

哪些资源能够被缓存?静态资源,(js,css,图片,与webpack打包加的hash有关,只有内容改变了,才会再次更改)

http缓存策略(强制缓存+协商缓存)

一、强制缓存
cache-contral 强制缓存,控制强制缓存的逻辑

cache-control:max-age=2592000 (秒)

image.png

max-age:过时时间

no-cache : 本地不作缓存

no-store:本地不缓存,服务器端也不缓存。

关于Expires

二、协商缓存(对比缓存)

Last-Modified: 最后一次修改的时间
Etag: 人类的指纹,惟一的标识,字符串

二者共存,会优先使用Etag,Etag会更加精准。

总结: 就是请求服务端,问问服务端本地的能不能用。

image.png

image.png

image.png

刷新操做方式 对缓存的影响

正常操做:url的前进后退; 都有效

手动刷新:强制缓存失效,协商缓存有效

强制缓存:contral + command + 2 都失效

相关文章
相关标签/搜索