面试问题

1 typescript

1.1 什么是 TypeScript

TypeScript 是微软开发一款开源的编程语言,它是 JavaScript 的一个超集,本质上是为 JavaScript 增加了静态类型声明。任何的 JavaScript 代码都可以在其中使用,不会有任何问题。TypeScript 最终也会被编译成 JavaScript,使其在浏览器、Node 中等环境中使用。

算法

2.1 冒泡排序

bubblesort (arr){
        let len = arr.length;
 //外层循环,控制趟数,每一次找到一个最大值
        for(let i = 0; i < len - 1; i++){
// 内层循环,控制比较的次数,并且判断两个数的大小
            for(let j = 0;j < len - 1 - i; j++){
                if(arr[j] > arr [j+1]){
                    let temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        return arr;

    }

2.2 快速排序

  • 实现1
    基本思路:
  1. 在将要排序的数据中选取一个数作为基准数,将这些数据中比所选取的基准数小的数放在所选取基准数的左边为左数组,将比所选取基准数大的数组放在右边为右数组。
  2. 通过递归的方式重复循环1中的过程达到排序的目的。
// 快速排序
    
    quickSort(arr){
        if(arr.length < 2) return arr;
        let leftArr = [],rightArr = [] ,enArr = [],beginData = arr[0];
        arr.forEach(item=>{
            if(item > beginData){
                rightArr.push(item);
            }
            if(item < beginData){
                leftArr.push(item)
            }
            if(item == beginData){
                enArr.push(item)
            }

        })
        return this.quickSort(leftArr).concat(enArr,this.quickSort(rightArr));
    }
  • 实现2
  quickSort2 (arr,begin,end){
        //递归出口
        if(begin >= end) return;
        let l = begin,// // 左指针
            r=end, //右指针
            beginData = arr[begin]; //基准数,这里取数组第一个数
        //左右指针相遇的时候退出扫描循环
        while(l= beginData)
                r--;
            //左指针从左向右扫描,碰到第一个大于基准数的时候停住
            while (l < r && arr[l] <= beginData)
                l++;
            // let temp = arr[r];
            // arr[r] = arr[l];
            // arr[l] = temp;
            //交换左右指针所停位置的数
            [arr[l], arr[r]] = [arr[r], arr[l]];
        }
        //最后交换基准数与指针相遇位置的数
        [arr[begin], arr[l]] = [arr[l], arr[begin]];
        //递归处理左右数组
        this.quickSort2(arr, begin, l - 1);
        this.quickSort2(arr, l + 1, end);
        return arr;
    }

2.3 插入排序

算法理解:
插入排序就是把一组数字分成两部分,一部分是排好顺序的,另一部分是没有排好顺序的,然后,就是从没有排好顺序的那组数字中获取数字,把它插入到已经排好的顺序的那部分数字中,当然,在插入到已经排好顺序的那部分数字时,你还必须让这个插入进来的数字与已经排好顺序的数字进行比较,为的是保证已经排好的顺序的那部分数字不被打乱,插入排序的关键也就是这里,如果能够理解这里,我想对于接下来我写的代码应该不难理解了。

//外层循环取数,内层循环在有序中比较
insertSort (arr){
        let len = arr.length;
        for (let i = 1; i < len; i++) {
            for(var j=i-1;j>=0;j--){//注意,j--,就是从有序部分的后面元素开始和无序部分的元素作比较
                if(arr[j] > arr[j+1]){//第一次循环的第一个j+1也就是外层循环i,
                    //互换元素,对前面数组进行排序
                    var temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }
            }
        }
        return arr;
    }

2.4 选择排序

首先从原始数组中找到最小的元素,并把该元素放在数组的最前面,然后再从剩下的元素中寻找最小的元素,放在之前最小元素的后面,直到排序完毕。

// 选择排序
    selectSort (arr){
        let temp,minindex;
        let len = arr.length;
        for(let i = 0; i< len; i++){
            minindex = i;
            for(let j = i+1;j

2.5 深拷贝实现

// 判断是否为对象
function isObject(obj){
        return typeof obj === 'object' && obj != null
}
function CloneDeep(source){
    // 判断复制的目标书数组还是对象
        if(!isObject(source)) return source;
    var targetObj = source.constructor === Array ? [] : {};
    for(let keys in source){
        //判断对象是否包含特定的自身(非继承)属性。
        if(source.hasOwnProperty(keys)){
            //判断是否是对象或者数组
            if(source[keys] && isObject(source[keys])){
                targetObj = source.constructor === Array ? [] : {};
                targetObj[keys] = CloneDeep(source[keys]);// 递归调用
            }else{
                targetObj[keys] = source[keys];
            }
        }
    }
    
    return targetObj;

}

3 HTTP协议相关

3.1 HTTP是什么

http(超文本传输协议),基于TCP/IP,在计算机世界里专门在两点之间传输文字、图片、音频和视频等超文本数据的约定和规范

3.2 输入网址,按下回车究竟发生了什么

1、 浏览器先判断输入地址栏的是不是数字形式的IP地址,如果不是,肯定就是域名了,于是就发起域名解析动作,访问一系列的域名解析服务器,把域名翻译成TCP/IP协议里的IP地址(域名解析比较复杂,如果每一个域名都要大费周折的网上查一下,那我们上网肯定慢的受不了,所以,域名解析过程中会有多级缓存,浏览器会先看自己的缓存有没有,再看操作系统的缓存,还没有就检查本机的域名解析文件hosts[c:\windows\system32\drivers\etc\hosts]),通过解析获得IP地址和端口号
2、 浏览器使用TCP的三次握手和服务器建立连接
3、 浏览器向服务器发送拼接好的报文
4、 服务器收到报文后处理请求,同样拼接号报文再发送给浏览器
5、 浏览器解析报文,渲染输出页面

3.2 什么是CORS

CORS(跨域资源共享 Cross-origin resource sharing)允许浏览器向跨域服务器发出XMLHttpRequest请求,从而克服跨域问题,它需要浏览器和服务器的同时支持。

  • 浏览器端会自动向请求头添加origin字段,表明当前请求来源。
  • 服务器端需要设置响应头的Access-Control-Allow-Methods,Access-Control-Allow--
    Headers,Access-Control-Allow-Origin等字段,指定允许的方法,头部,源等信息。
  • 请求分为简单请求和非简单请求,非简单请求会先进行一次OPTION方法进行预检,看是否允许当前跨域请求

3.3 作用域链

当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链

3.4 什么是闭包

闭包指能够访问自由变量(自由变量指的是在函数中使用,但既不是函数参数也不是函数局部变量的变量)的函数

3.5 get请求和post请求的详细区别

  • GET把参数包含在URL中,POST通过request body传递参数。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。

3.5 new操作符调用构造函数

  • 创建一个新的对象
  • 将构造函数的this指向这个新对象
  • 为这个对象添加属性,方法等
  • 返回新对象

3.6 改变函数内部this指针的指向函数(bind,apply,call的区别)

  • 通过apply和call改变函数的this指向,他们两个函数的第一个参数都是一样的表示要改变指向的那个对象,第二个参数,apply是数组,而call则是arg1,arg2...这种形式。
  • 通过bind改变this作用域会返回一个新的函数,这个函数不会马上执行

3.7 js的各种位置,比如clientHeight,scrollHeight,offsetHeight ,以及scrollTop, offsetTop,clientTop的区别

  • clientHeight:表示的是可视区域的高度,不包含border和滚动条
  • offsetHeight:表示可视区域的高度,包含了border和滚动条
  • scrollHeight:表示了所有区域的高度,包含了因为滚动被隐藏的部分。
  • clientTop:表示边框border的厚度,在未指定的情况下一般为0
  • scrollTop:滚动后被隐藏的高度,获取对象相对于由offsetParent属性指定的父坐标(css定位的元素或body元素)距离顶端的高度。

3.8 Promise

//定义三种状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function MyPromise(fn) {
    let self = this;// 缓存当前promise实例
    self.value = null; //成功时的值
    self.error = null; //失败时的原因
    self.status = PENDING; // 当前状态
    self.onFulfilled = null; //成功的回调函数
    self.onRejected = null; 失败的回调函数

    function resolve(value) {
        //如果状态是pending才去修改状态为fulfilled并执行成功逻辑
        if (self.status === PENDING) {
            setTimeout(function() {
                self.status = FULFILLED;
                self.value = value;
                self.onFulfilled(self.value);
            })
        }
    }

    function reject(error) {
        //如果状态是pending才去修改状态为rejected并执行失败逻辑
        if (self.status === PENDING) {
            setTimeout(function() {
                self.status = REJECTED;
                self.error = error;
                self.onRejected(self.error);
            })
        }
    }
    fn(resolve, reject);
}
MyPromise.prototype.then = function(onFulfilled, onRejected) {
    if (this.status === PENDING) {
        this.onFulfilled = onFulfilled;
        this.onRejected = onRejected;
    } else if (this.status === FULFILLED) {
        //如果状态是fulfilled,直接执行成功回调,并将成功值传入
        onFulfilled(this.value)
    } else {
        //如果状态是rejected,直接执行失败回调,并将失败原因传入
        onRejected(this.error)
    }
    return this;
}
module.exports = MyPromise

3.9 Cookie、sessionStorage、localStorage的区别

  • 共同点:都是保存在浏览器端,并且是同源的
  • Cookie:cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
  • sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持,localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭

补充说明一下cookie的作用:

  • 保存用户登录状态。例如将用户id存储于一个cookie内,这样当用户下次访问该页面时就不需要重新登录了,现在很多论坛和社区都提供这样的功能
  • 跟踪用户行为。例如一个天气预报网站,能够根据用户选择的地区显示当地的天气情况。如果每次都需要选择所在地是烦琐的,当利用了 cookie后就会显得很人性化了,系统能够记住上一次访问的地区,当下次再打开该页面时,它就会自动显示上次用户所在地区的天气情况
  • 定制页面。如果网站提供了换肤或更换布局的功能,那么可以使用cookie来记录用户的选项,例如:背景色、分辨率等。当用户下次访问时,仍然可以保存上一次访问的界面风格。

你可能感兴趣的:(面试问题)