黑马程序员技术交流社区

标题: 【西安校区】十道前端面试题 [打印本页]

作者: 逆风TO    时间: 2019-10-22 17:33
标题: 【西安校区】十道前端面试题
1. call apply bind的区别?
相同点: 都可以改变函数调用的this指向
不同点:

call和apply的用法几乎相同,唯一不同就是参数不同。call只能一个一个参数传入,apply参数是一个数组。
bind的传参方式和call相同,但是改变调用函数的指向并返回一个新的函数,之后再调用这个函数时候this就指向bind绑定的第一个参数
call语法

fun.call(thisArg,arg1,arg2,...)
thisArg是fun函数运行时指定的this值(在非严格模式下,指定为null或undefined时会自动指向全局对象)
arg1,arg2,...是指定的参数列表
apply语法

fun.apply(thisArg, [argsArray])
thisArg是fun函数运行时指定的this值(在非严格模式下,指定为null或undefined时会自动指向全局对象)
argsArray是一个数组或类数组对象,数组中的元素将作为单独的参数传给fun函数,如果 argsArray为null或undefined时表示不需要传入任何参数。
示例:
数组没有max方法,可以使用Math对象上的max方法

const arr = [1,2,3,4,5,6];
const max = Math.max.apply(null,arr);  // 6

bind语法

fun.bind(thisArg,arg1,arg2,...)
thisArg当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new 操作符调用绑定函数时,该参数无效。
arg1, arg2, ...当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
// 如果你某个函数绑定新的this指向并且固定先传入几个变量可以在绑定的时候就传入,之后调用新函数传入的参数都会排在之后
const obj = {}
function test(...args) {
        console.log(args);
}
const newFn = test.bind(obj, 1,2);
newFn(3,4);     // [1,2,3,4]

使用场景

当一个函数需要改变this指向时
且参数较少时可以使用call
如果参数较多,可以将参数整理到一个数组,使用apply
如果想生成一个新函数长期绑定某个对象时,可以使用bind
2. 数组去重
方法一:
这是个没有什么技术含量的方法(使用了ES6 Set数据结构)!
        let arr = [1,1,1,1,2,3,4,5,5,6];
        arr = [...new Set(arr)];       // [1,2,3,4,5,6]

方法二:
for循环嵌套for循环
function unique(arr){
        for(let i = 0; i<arr.length; i++) {
                for(let j = i+1; j < arr.length; j++) {
                        if(arr[i] === arr[j]){
                                arr.splice(j,1);   // 去除重复的这个
                                j--;
                        }
                }
        }
        return arr;
}

方法三
使用indexOf方法,或数组的includes方法
function unique(arr) {
        let arr1 = [];
        for(let i=0; i<arr.length; i++) {
                if(arr1.indexOf(arr[i]) === -1) {  // !arr1.includes(arr[i])
                        arr1.push(arr[i]);      // 如果arr1中不存在该元素则push进arr1
                }       
        }
        return arr1;
}

方法四
利用sort排序后,相邻元素进行对比
function unique(arr) {
        arr.sort( (a,b) => a-b);
        for(let i=0; i< arr.length-1; i++){
                if(arr[i] === arr[i+1]) {
                        arr.splice(i+1,1);
                }
        }
        return arr;
}


当然不只这几种方法。。欢迎评论补充

3. http状态码(点击跳转)
4. CSS弹性布局(点击跳转)
5.position属性有哪些值,分别有什么含义
position属性规定元素的定位类型

属性值        描述
absolute        生成绝对定位的元素。相对于除了static定位以外的第一个父元素定位
fixed        生成绝对定位的元素,相对于浏览器窗口定位
relative        生成相对定位元素,相对于自己原来的位置定位
static        默认值。没有定位,元素出现在正常流中(忽略 top, bottom, left, right 或者 z-index 声明)
inherit        继承父元素position的值
6. const和let的区别,可以改变const定义对象某个属性吗
const与let都只在声明的块级作用域内有效
let声明的变量可以改变,值和类型都可以改变,且可以先声明,后赋值。
const声明一个常量,值不可以改变,且一旦声明就得赋值。
对于const声明一个引用类型的变量(如:数组,对象),变量名不指向数据,而是指向引用类型数据所在的地址(即变量保存的是指向这个引用类型的指针),因此可以改变const定义对象的某个属性值。
7. this的理解, 如何改变this的指向
this值函数运行时所在的环境(即调用的对象)
可以理解为谁调用函数,this就指向谁
可以上述序号1的call,apply,bind方法改变this指向
8. let和var的区别,let的产生背景?
let声明变量会形成块级作用域,var不能
let声明变量只能先声明后使用(暂时性死区),即let不存在变量提升
示例:

{
        let a =1;
}
console.log(a);   // a is not defined

9. var的变量提升底层原理是什么
JS引擎的工作方式:

先解析代码,获取所有声明的变量
然后再运行
也就是分为预处理和执行两个阶段

变量提升的定义: 所有的变量声明语句会被提升到声明变量所在作用域的头部
定义与赋值分离

示例:

console.log(a);    // 报错 a is not defined

console.log(b);   // undefined
var b = 1;

上面的代码相当于:

var b;
console.log(b);    // undefined
b = 1;

10. 箭头函数,箭头函数的特点
相比普通函数更简洁的语法
本身没有this,捕获其所在上下文(作用域)的this值,作为自己的 this 值
不能使用new
不绑定arguments,用rest参数...解决
使用call()和apply()调用
箭头函数没有原型属性
不能简单返回对象字面量
箭头函数不能当做Generator函数,不能使用yield关键字







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2