头条内推面补坑-更新中

老样子,答的好的这里就不写了。只记录答的不好的的。
这次暴露出来的问题就是要多做项目,多实践。

1.改这个代码

//目标代码
const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function () {
        for (var i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(function(){
                console.log(i);
                console.log(this.skill[i]);
            }, 0)
            console.log(i);
        }
    }
};
obj.say();

第一种:

const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function ()
    {
        var that = this;
        for (var i = 0, len = this.skill.length; i < len; i++)
        {
            setTimeout((function()
            {
                console.log(i);
                console.log(that.skill[i]);
            })(i), 0)
            console.log(i);
        }
    }
};
obj.say();

结果:
这里写图片描述
面试官当时就让我写在浏览器里的,但是我当时使用的webstorm,用的node环境,就报错了,结果就很慌。。。。。搞得最后不敢交。。这个代码可以在浏览器中执行的。

第二种:
同时在Node和浏览器(chrome)中都可以实现的:

const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function ()
    {
        var that = this;
        for (let i = 0, len = this.skill.length; i < len; i++)
        {
            (function () {
                setTimeout(function () {
                    console.log(i);
                    console.log(that.skill[i])
                })
            })(i)
            console.log(i);
        }
    }
};
obj.say();

结果是这样
这里写图片描述

两种结果虽然取到了我们想要的结果,但是和外层的console.log(i)出现了顺序的差异。第二种写法先打印完这个,再依次打印()()自执行函数的。
应该是执行第一个script宏任务的时候,遇到了三个()(),把这三个推进了微任务,当第一个宏任务结束之后,依次执行完本次遇到的所有的微任务。

第一种顺序打印,是因为每个setTimeout即是一次宏任务。但如果把setTimeout包括起来就是微任务了。

其他更多骚方法我都写在这里:

const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function () {
        this.skill.forEach(function(item,index){
            setTimeout(function(){
                console.log(index)
                console.log(item);
            },0)
        })
    },
    say2:function(){
        for (var i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(function(i,item){
                console.log(i);
                console.log(item);
            },0,i,this.skill[i]);
        }
    },
    say3:function () {
        let i = 0;
        const arr = this.skill.slice();
        function self_shift() {
            //shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。空返回undefined
            const item = arr.shift();
            if(item) {
                console.log(i);
                console.log(item);
                i++;
                setTimeout(self_shift, 0);
            }
        }
        setTimeout(self_shift,0);
    }
};
obj.say();
obj.say2();
obj.say3();

// 闭包了,里面的i跟外面的i不是同一个,加上自执行
const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function () {
        for (var i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(((j) => {
                return () => {
                    console.log(j);
                    console.log(this.skill[j]);
                }
            })(i), 0)
            console.log(i);
        }
    }
};
obj.say();

const obj = {
    name: " jsCoder",
    skill: ["es6", "react", "angular"],
    say: function () {
        var that = this;
        for (let i = 0, len = this.skill.length; i < len; i++) {
            setTimeout(function(){
                console.log(i);
                console.log(that.skill[i]);
            }, 0)
            console.log(i);
        }
    }
};
obj.say();

2.手写bind,bind还有其他什么作用?

这个问题挺好的,我单独开了另一篇博客来谈谈这个问题:
https://blog.csdn.net/major_zhang/article/details/79709370

3.什么时候304什么时候200,相关浏览器缓存问题?

  1. 在浏览器第一次请求某一个URL时,服务器端的返回状态会是200,内容是你请求的资源,同时有一个Last-Modified的属性标记此文件在服务期端最后被修改的时间,:
    Last-Modified: Fri, 12 May 2006 18:53:33 GMT

  2. 客户端第二次请求此URL时,根据 HTTP 协议的规定,浏览器会向服务器传送 If-Modified-Since 报头,询问该时间之后文件是否有被修改过:
    If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT
    服务器端的程序先取得这个字段的值,然后与服务器上的数据最后修改时间对比,如果服务器端的资源没有变化,就直接返回 304 Not Modified 状态码,然后停止。这样就节省了传输数据量,达到节省带宽的目的。当服务器端代码发生改变或者重启服务器时,则重新发出资源,返回和第一次请求时类似。(发送200?)从而保证不向客户端重复发出资源,也保证当服务器有变化时,客户端能够得到最新的资源。

  3. 但是Last-Modified不是全能的,后来在Http1.1加入了Etag来标记,Etag的精确度更高
    想象在这个一个情景——客户端上某个资源保存的缓存时间过期了,但这时候其实服务器并没有更新过这个资源,如果这个资源数据量很大,客户端要求服务器再把这个东西重新发一遍过来,是否非常浪费带宽和时间呢?
    所以就有了Etag:
    当你第一次请求一个资源的时候,server会同时生成并返回一个字符串在响应头里,叫Etag。
    浏览器接到资源后,缓存资源的同时也会把这个Etag保存下来,成为If-None_Match 。Etag可以看作是一个资源的唯一标识,当你第二次请求这个资源的时候,请求头里会带着这个Etag,server会拿server该资源现在的Etag跟请求头中的If-None_Match做对比,然后看看If-Modified-Since过没过期,如果一样,直接告诉他:你就用本地的吧,我没变,就不给你返回了。所以返回了304,304就是这样。

  4. 200 From Cache
    这个虽然是200,但他根本就没有跟server做交互,直接拉的本地缓存。

  5. 与浏览器缓存相关的还有Expires字段,这个字段存储的时间是相对服务器而言,无法保证和客户端时间统一”的问题,http1.1新增了 Cache-Control 来定义缓存过期时间,若报文中同时出现了 Pragma、Expires 和 Cache-Control,会以 Cache-Control 为准。Last-Modified之后的Etag就是为了解决,因为如果在服务器上,一个资源被修改了,但其实际内容根本没发生改变,会因为Last-Modified时间匹配不上而返回了整个实体给客户端(即使客户端缓存里有个一模一样的资源)。

4.手写一个jsonp,怎么返回数据的?

猜你喜欢

转载自blog.csdn.net/major_zhang/article/details/79688089