前端面试题

  1. Div中有n个按钮, 实现点击按钮 打印按钮的value值.

<div id=”hd” >

        <button>btn1</button>

        <button>btn2</button>

        <button>btn3</button>

        <button>btn4</button>

        …

</div>

let btns = document.getElementById('hd').getElementsByTagName('button');

for(let item of btns){

 item.onclick = function(){

  console.log(this.innerHTML)

}

}

 

  2. 用最简单的代码编写一个闭包, 简单描述闭包的优缺点.

//todo

Function foo1(param){

        var x = param || 0;

        return {

        add:function(){

              x += 1;

               return x;

    }

  }

}

//调用

Var foo2 = foo1();

Foo2.add();// 1

Foo2.add();// 2

Foo2.add();// 3

    

闭包的优点:1.能够读取函数内部的变量 2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收

闭包的缺点:正所谓物极必反,由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除。

    3. 深拷贝和浅拷贝

a)    区别

       浅拷贝(shallow copy):只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存;

  深拷贝(deep copy):复制并创建一个一摸一样的对象,不共享内存,修改新对象,旧对象保持不变。

b)    编写一个方法, 实现对一个复杂对象的深拷贝

//(输写区)

let foo = {

a: 1,

b: 2,

c: {

  d: 1,

  }

}

let bar = {};

Object.assign(bar, foo);

console.log(bar)

bar.a = 122

console.log(foo,bar)

    4.有数组如下

var arr1 = [{name: “lilei”}, {name: “hmm”}, {name: “lucy”}, {name: lilei}];

请使用es5代码对上述数组去重

function unique(a) {

  var res = a.filter(function(item, index, array) {

    return array.indexOf(item) === index;

  });

    return res;

}

var a = [1, 1, '1', '2', 1];

var ans = unique(a);

console.log(ans);

5. 写出运行结果

Class Animal {

        constructor() {

               this.type = “animal”;

        }

        Say (say) {

               setTimeout(function () {

                      console.log(this.type + “says” + say);

               }, 1000)

        }

}

New Animal().Say(“hi”);

输出结果:undefinedsayshi

 

   6. apply, call, bind 的相同点和不同点.

    相同点:

1】都是用来改变函数的this对象的指向的。
2】第一个参数都是this要指向的对象。
3】都可以利用后续参数传参。

不同点:

1】call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数,因此后面还需要()来进行调用才可以;

2】call后面的参数与say方法中是一一对应的,而apply的第二个参数是一个数组,数组中的元素是和say方法中一一对应的,这就是两者最大的区别;

示例:

       var a = {

              name:’Karila’,

              age:’24’,

              say:function(school,grade){

                     console.log(this.name + this.age + school + grade)

    }

  }

var b = {

              name:’April’,

              age:’24’,

}

a.say.call(b,’学校’,’成绩’);a.say.apply(b,[’学校’,’成绩’]);

a.say.bind(b,’学校’,’成绩’)();a.say.bind(b)( ’学校’,’成绩’)

 

7. 常见的数据类型有哪些?

js数据类型,包括五种简单数据类型——Number,String,Boolean,Undefined,Null,和一种复杂数据类型——Object。

typeof 操作符

由于js中的变量是松散类型的,所以它提供了一种检测当前变量的数据类型的方法,也就是typeof关键字.

typeof   123   //Number

typeof   'abc'  //String

typeof    true       //Boolean

typeof    undefined   //Undefined

typeof    null        //Object

typeof    { }           //Object

typeof    [ ]           //Object

typeof    console.log()       //Function

null类型进行typeof操作符后,结果是object,原因在于,null类型被当做一个空对象引用。

8.解释一下this的具体含义;

  this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this指向那个对象;匿名函数的执行环境具有全局性,因此其this对象通常指向window;

9.列出JS当中继承的几种方法:

  1】组合继承:指的是将原型链和借用构造函数的技术组合到一块,思路是:使用原型链实现对原型的属性和方法的继承,而通过借用构造函数来实现对实例属性的继承;

2】原型式继承:在一个函数object()内部新建一个临时性的构造函数,将传入的对象作为这个构造函数的原型,最后返回这个临时类型的新实例。本质上讲:object()对传入其中的对象执行了一次浅拷贝;

3】寄生式继承:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式增强对象,最后再像真的是他做了所有工作一样返回对象。

4】寄生组合式继承:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法;背后的思路是:不必为了指定子类型的原型来调用超类型的构造函数,我们所需的无非就是超类型原型的一个副本。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

代码示例:  //组合继承:原型链+借用构造函数

    function SuperType(name){
this.name = name;
this.colors = ['blue','yellow','pink']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name,age){

SuperType.call(this,name);
this.age = age
}

SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
console.log(this.age)
}
var instance1 = new SubType('Lily',29);
instance1.colors.push('black');
console.log(instance1)
console.log(instance1.colors)
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType('Bob',36);
console.log(instance2.colors)
instance2.sayName();
instance2.sayAge();

//原型式继承
function object(o){
function F(){};
F.prototype = o;
return new F()
}
var person = {
name:'Nicholas',
friends:['Shirly','April','Bob']
}

var personOne = object(person);
personOne.name = 'Lily';
personOne.friends.push('Barbie');

var personTwo = object(person);
personTwo.name = 'Linda';
personTwo.friends.push('Van')

//寄生式继承
function object(o){
function F(){};
F.prototype = o;
return new F()
}
function createAnother(original){
var clone = object(original);
clone.sayHi = function(){
alert('Hi')
};
return clone;
}
var anotherPerson = createAnother(person);
console.log(anotherPerson)
anotherPerson.sayHi()

//寄生组合式继承
function SuperType(name){
this.name = name;
this.colors = ['blue','yellow','pink']
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name,age){

SuperType.call(this,name);
this.age = age
}
function inheritPrototype(subType,superType){
var prototype = object(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
console.log(this.age)
}
var instance1 = new SubType('Lily',29);
instance1.colors.push('black');
console.log(instance1)
console.log(instance1.colors)
instance1.sayName();
instance1.sayAge();

var instance2 = new SubType('Bob',36);
console.log(instance2.colors)
instance2.sayName();
instance2.sayAge();
 10.常见的字符串方法   

charAt(num) // 得到指定索引位置的单字符

charCodeAt(num) // 得到指定索引位置字符的Unicode值 (ascii为其子集)

concat(str01,str02) // 连接俩字符~

indexOf("str") // 取str第一次出现的索引

lastIndexOf("str") // 取str最后一次出现的索引

replace( "oldStr" , "newStr" ) // 找到oldStr替换为newStr

slice( start , end ) // 其对象可以是字符串or数组 , 记得其范围不包括end

substr( start , length ) // 从索引start开始取length个字符 , length不可小于0否则返回空字符串

search("str") // 在str01中搜索字符串"str" , 返回其第一个字符在str01中的索引

String.fromCharCode(uniNum,uniNum) // 参数为Unicode值 ( >=1个即可)

str01.localeCompare(str02) // 以本地特定规则比较 , 若str01>str02 = 1 反之-1 相等为0
str03 = str02.valueOf() ; // 可返回字符串对象(str02)的原始值

str03 = str01.split("str") // 将原字符串分割为一个数组对象 , 分隔符为逗号 , 参数为 空 空格 字符串

var n = num.toString() // 将Number对象=>String对象(n为字符) , 源对象没变

  11.常见的数组方法
  
 (1) shift(): //删除数组的第一个元素,返回删除的值。

     (2) unshift( i , j ): //在数组的前面添加

     (3) pop(): //删除数组的最后一个元素,并返回删除的值。

(4)push(param): //在数组的最后添加

(5)concat( i , j ): //将参数与数组拼接起来

(6) splice(start,deleteCount,val1,val2,...):从start位置开始删除deleteCount项,并从该位置起插入val1,val2,... 

(7) reverse:将数组反序 
  var a = [1,2,3,4,5]; 
  var b = a.reverse(); //a:[5,4,3,2,1] b:[5,4,3,2,1] 

(8) sort(orderfunction):按指定的参数对数组进行排序 
  var a = [1,2,3,4,5]; 
  var b = a.sort(); //a:[1,2,3,4,5] b:[1,2,3,4,5] 

(9) slice(start,end):返回从原数组中指定开始下标到结束下标之间的项组成的新数组 
  var a = [1,2,3,4,5]; 
  var b = a.slice(2,5); //a:[1,2,3,4,5] b:[3,4,5] 

(10) join(separator):将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符 
  var a = [1,2,3,4,5]; 
  var b = a.join("|"); //a:[1,2,3,4,5] b:"1|2|3|4|5"

 








原文地址:https://www.cnblogs.com/xunhuang/p/9364148.html