CruxF / Blog

个人博客,记载学习的点点滴滴,怕什么技术无穷,进一寸有一寸的欢喜:sparkles:

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

前端开发面试题——JavaScript

CruxF opened this issue · comments

前言

本文收集了一些前端面试题,主要是为了今后的求职,同时也借助这些面试题更进一步系统的学习、透彻的学习,形成自己的知识链。这并不是投机取巧,临时抱佛脚哈,自己也明白如果这么做肯定对未来的发展不利。

JavaScript

1、JavaScript对数组的操作方法有哪些?

(1)join()方法:接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串
(2)push()方法:接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度
(3)pop()方法:从数组末尾移除最后一项,减少数组的length值,然后返回移除的项
(4)shift()方法:移除数组中第一个项并返回改项,同时将数组长度减1
(5)unshift()方法:在数组前端添加任意个项并返回新数组的长度
(6)sort()方法:对数组中的数据进行排序
(7)concat()方法:可以基于当前数组中的所有项创建一个新数组
(8)slice()方法:基于当前数组中的一或多个项创建一个新数组
(9)indexOf()方法:从数组的开头(位置0)开始向后查找
(10)lastIndexOf():从数组的末尾开始向前查找
(11)splice()方法:恐怕要算是最强大的数组方法了,它有很多种用法,splice()的主要用途是向数组的中部插入项,但使用这种方法的方式则有如下3种:

  • 删除:可以删除任意数量的项,只需指定2个参数(要删除的第一项的位置和要删除的项数),例如:splice(0,2)会删除数组中的前两项
  • 插入:可以向指定位置插入任意数量的项,只需要提供3个参数(起始位置,0(要删除的项数)和要插入的项),例如:splice(2,0,"red","green")会从当前数组的位置2开始插入字符串"red"和"green"
  • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需要提供3个参数(起始位置,要删除的项数和要插入的任意数量的项),例如:splice(2,1,"red","green")会删除当前数组位置2的项,然后再从位置2开始插入字符串"red"和"green";
    原文地址

数组面试题
(1)计算给定数组arr中所有元素的总和

function sum(arr) {
  var result = 0;
  for (var i = 0; i < arr.length; i++) {
    result += arr[i];
  }
  return result;
}
var arr = [4,5,6,1];
console.log(sum(arr));

(2)合并数组 arr1 和数组 arr2,不要直接修改数组 arr,结果返回新的数组

function concat(arr1, arr2) {
  var arr3 = arr1.concat(arr2);
  return arr3;
}
var Arr1 = [4, 5, 2];
var Arr2 = [7, 8, 3];
console.log(concat(Arr1, Arr2));

(3)删除数组 arr 第一个元素,不要直接修改数组 arr,结果返回新的数组

function curtail(arr) {
  var arr2 = arr.slice(0);
  arr2.shift();
  return arr2;
}
var Arr = [1, 2, 34, 5];
console.log(curtail(Arr));

(4)在数组 arr 开头添加元素 item,不要直接修改数组 arr,结果返回新的数组

function prepend(arr, item) {
  var arr2 = arr.slice(0);
  arr2.unshift(item);
  return arr2;
}

(5)移除数组 arr 中的所有值与 item 相等的元素,直接在给定的 arr 数组上进行操作,并将结果返回

function removeWithoutCopy(arr, item) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == item) {
      arr.splice(i, 1);
      i--;
    }
  }
  return arr;
}
var Arr = [3, 4, 5, 6, 6, 6, 1];
console.log(removeWithoutCopy(Arr, 6));

(6)找出元素 item 在给定数组 arr 中的位置

function indexOf(arr, item) {
  for (var i = 0; i < arr.length; i++) {
    if (arr[i] == item) {
      return i;
    }
  }
  return -1;
}

2、JavaScript如何设置获取盒模型对应的宽和高?

(1)dom.style.width/height(只能获取到内联样式的宽和高,输出值带单位)

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
  </head>
  <body>
    <div id="box" style="height: 200px;"></div>
    <script>
      var getHeight = document.getElementById("box");
      console.log(getHeight.style.height);
    </script>
  </body>
</html>

(2)dom.currentStyle.width/height(只有IE浏览器支持,输出值带单位)

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      #box {
        height: 200px;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script>
      var getHeight = document.getElementById("box");
      document.write(getHeight.currentStyle.height);
    </script>
  </body>
</html>

(3)window.getComputedStyle(dom).width/height(兼容性好,输出值带单位)

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      #box {
        height: 200px;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script>
      var getHeight = document.getElementById("box");
      document.write(window.getComputedStyle(getHeight).height);
    </script>
  </body>
</html>

(4)dom.getBoundingClientRect().width/height(兼容性好,输出值不带单位)

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      #box {
        height: 200px;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script>
      var getHeight = document.getElementById("box");
      document.write(getHeight.getBoundingClientRect().height);
    </script>
  </body>
</html>

3、DOM事件的级别

(1)DOM0:element.onclick = function(){}
(2)DOM2:element.addEventListener('click',function(){},false)
【拓展】
所谓的0级dom与2级dom事件就是不同版本间的差异,具体的说就是,对于不同的dom级别,如何定义事件处理,以及使用时有什么不同。 比如在dom0级事件处理中,后定义的事件会覆盖前面的,但是dom2级事件处理中,对一个按钮点击的时间处理就没有被覆盖掉。
(3)DOM3:element.addEventListener('keyup',function(){},false)

4、DOM事件模型

(1)冒泡型事件处理模型(Bubbling):冒泡型事件处理模型在事件发生时,首先在最精确的元素上触发,然后向上传播,直到根节点,反映到DOM树上就是事件从叶子节点传播到根节点。
(2)捕获型事件处理模型(Captrue):相反地,捕获型在事件发生时首先在最顶级的元素上触发,传播到最低级的元素上,在DOM树上的表现就是由根节点传播到叶子节点。
【捕获事件的具体流程】
window==>document==>html==>body==>父级元素==>目标元素
(3)标准的事件处理模型分为三个阶段:

  • 父元素中所有的捕捉型事件(如果有)自上而下地执行
  • 目标元素的冒泡型事件(如果有)
  • 父元素中所有的冒泡型事件(如果有)自下而上地执行

5、Event对象的常见应用

(1)event.preventDefault():阻止事件的默认行为
(2)event.stopPropagation():阻止事件的进一步传播,也就是阻止冒泡
(3)event.stopImmediatePropagation():阻止剩余的事件处理函数的执行,并防止当前事件在DOM树上冒泡。
(4)event.currentTarget:返回绑定事件的元素
(5)event.target:返回触发事件的元素

6、JavaScript自定义事件

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Event</title>
    <style>
      html * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div id="ev">
      <span>目标元素</span>
    </div>
    <script>
      var event = new Event('test');
      ev.addEventListener('test', function () {
        console.log('test dispatch');
      })
      ev.dispatchEvent(event);
    </script>
  </body>
</html>

7、JavaScript类的声明

// 1、类的声明
function Animal() {
  this.name = "name";
}
// 2、ES6中类的声明
class Animal2 {
  constructor() {
    this.name = name;
  }
}
// 3、实例化类
console.log(new Animal(), new Animal2());

8、JavaScript类之间的继承

(1)借助构造函数实现不完全继承,无法继承方法:

function Parent1() {
  this.name = 'parent1';
}
function Child1() {
  Parent1.call(this);
  this.type = 'child1';
}
console.log(new Child1());

(2)借助原型链实现继承,所有的属性和方法都得去原型链上去找,因而找到的属性方法都是同一个,所以直接利用原型链继承是不现实的。

function Parent2() {
  this.name = 'parent2';
  this.play = [1, 2, 3];
}
function Child2() {
  this.type = 'child2';
}
Child2.prototype = new Parent2();
console.log(new Child2());
var s1 = new Child2();
var s2 = new Child2();
console.log(s1.play, s2.play);
s1.play.push(4);

(3)组合方式实现继承

function Parent3() {
  this.name = 'parent3';
  this.play = [1, 2, 3];
}
function Child3() {
  Parent3.call(this);
  this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play);

(4)组合继承的优化1

function Parent4() {
  this.name = 'parent4';
  this.play = [1, 2, 3];
}
function Child4() {
  Parent4.call(this);
  this.type = 'child4';
}
Child4.prototype = Parent4.prototype;
var s5 = new Child4();
var s6 = new Child4();
console.log(s5.play, s6.play);
console.log(s5 instanceof Child4, s5 instanceof Parent4);
console.log(s5.constructor);

(5)组合继承的优化2(俗称寄生式继承)

function Parent5() {
  this.name = 'parent5';
  this.play = [1, 2, 3];
}
function Child5() {
  Parent5.call(this);
  this.type = 'child5';
}
Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;
var s7 = new Child5();
console.log(s7 instanceof Child5, s7 instanceof Parent5);
console.log(s7.constructor);

9、创建对象有几种方法?

(1)字面量:

var k1 = {
  name: 'k1'
};
var k2 = new Object({
  name: 'k2'
});

(2)通过构造函数

var m = function (name) {
  this.name = name;
};
var k3 = new m('k3');

(3)通过Object.create

var p = {
  name: 'ppp'
};
var k4 = Object.create(p);

11、什么是原型和原型链?有什么特点?

(1)每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,如果这个对象不存在这个属性,那么就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。
(2)特点:JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。
(3)更多原型知识1

12、JavaScript的运行机制

(1)JavaScript是单线程,一个时间段内,JavaScript只能干一件事情。任务队列分为同步任务和异步任务。
(2)异步任务类型:setTimeout和setInterval、DOM事件、ES6中的Promise

13、JavaScript异步加载的方式

(1)动态脚本加载;
(2)defer
(3)async

14、JavaScript的typeof返回哪些数据类型?

Object number function boolean underfind、String;
【拓展】
比较混淆的是:介绍JavaScript的基本数据类型
答案为:Undefined、Null、Boolean、Number、String、Symbol(创建后独一无二且不可变的数据类型

15、JavaScript中的事件委托是什么?

事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

16、为什么要使用JavaScript的事件委托?

为了减少代码的DOM操作,提高程序性能。更多详情

17、JavaScript中的闭包

(1)有权访问另一个函数作用域内变量的函数都是闭包。
(2)闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!另外使用闭包也要注意变量的值是否符合你的要求,因为他就像一个静态私有变量一样。
(3)更多

18、window.onload和DOMContentLoaded的区别是?

window.addEventListener('load',function(){
    //页面的全部资源加载完才会执行,包括图片、视频等
})
document.addEventListener('DOMContentLoaded',function(){
    //DOM渲染完即可执行,此时图片、视频还可能没有加载完
})

19、用JavaScript创建10个标签,点击的时候弹出来对应的序号

var i;
for (i = 0; i < 10; i++) {
  (function (i) {
    var a = document.createElement('a');
    a.innerHTML = i + '<br>';
    a.addEventListener('click', function (e) {
      e.preventDefault();
      alert(i);
    });
    document.body.appendChild(a);
  })(i)
}

20、实现数组的随机排序

Array.prototype.shuffle = function () {
  var input = this;
  for (var i = input.length - 1; i >= 0; i--) {
    var randomIndex = Math.floor(Math.random() * (i + 1));
    var itemAtIndex = input[randomIndex];
    input[randomIndex] = input[i];
    input[i] = itemAtIndex;
  }
  return input;
}
var tempArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
tempArray.shuffle();
console.log(tempArray);

21、JavaScript中有哪些内置函数,与内置对象的区别是什么?

(1)内置函数:是浏览器内核自带的,不用任何函数库引入就可以直接使用的函数,如常规函数(alert等)、数组函数(reverse等)、日期函数(getDate等)、数学函数(floor等)、字符串函数(length等);
(2)内置对象:是浏览器本身自带的,内置对象中往往包含了内置函数。内置对象有Object、Array、Boolean、Number、String、Function、Date、RegExp等。

22、JavaScript变量按照存储方式区分为哪些类型,并描述其特点

//值类型
//变量的交换,按值访问,操作的是他们实际保存的值。
//等于在一个新的地方按照新的标准开了一个空间(栈内存),
//这样a的值对b的值没有任何影响
var a = 100;
var b = a;
b = 200;
console.log("a:" + a + ",b:" + b);
//引用类型
//变量的交换,当查询时,我们需要先从栈中读取内存地址,
//然后再顺藤摸瓜地找到保存在堆内存中的值;
//发现当复制的是对象,那么obj1和obj2两个对象被串联起来了,
//obj1变量里的属性被改变时候,obj2的属性也被修改。
var obj1 = {
  x: 100
};
var obj2 = obj1;
obj2.x = 200;
console.log("obj1:" + obj1.x + ",obj2:" + obj2.x);

23、如何理解JSON?

其实JSON只不过是一个JavaScript对象而已。stringify()是把对象变成字符串;parse()是把字符串变成对象。

24、JavaScript中&&和||

(1)只要“||”前面为false,不管“||”后面是true还是false,都返回“||”后面的值;
(2)只要“||”前面为true,不管“||”后面是true还是false,都返回“||”前面的值。
(3)且在js逻辑运算中,0、”“、null、false、undefined、NaN都会判为false,其他都为true。

(4)只要“&&”前面是false,无论“&&”后面是true还是false,结果都将返“&&”前面的值;
(5)只要“&&”前面是true,无论“&&”后面是true还是false,结果都将返“&&”后面的值。

25、描述new一个对象的过程

(1)创建空对象:var obj = {};
(2)设置新对象的constructor属性为构造函数的名称,设置新对象的__proto__属性指向构造函数的prototype对象:obj.proto = ClassA.prototype;
(3)使用新对象调用函数,函数中的this被指向新实例对象:ClassA.call(obj); //{}.构造函数();
(4)将初始化完毕的新对象地址,保存到等号左边的变量中
【注意】
若构造函数中返回this或返回值是基本类型(number、string、boolean、null、undefined)的值,则返回新实例对象;若返回值是引用类型的值,则实际返回值为这个引用类型。

26、什么是构造函数?

(1)构造函数就是初始化一个实例对象,对象的prototype属性是继承一个实例对象。
(2)注意事项:

  • 默认函数首字母大写;
  • 构造函数并没有显示返回任何东西。new 操作符会自动创建给定的类型并返回他们,当调用构造函数时,new会自动创建this对象,且类型就是构造函数类型;
  • 也可以在构造函数中显示调用return.如果返回的值是一个对象,它会代替新创建的对象实例返回。如果返回的值是一个原始类型,它会被忽略,新创建的实例会被返回;
  • 因为构造函数也是函数,所以可以直接被调用,但是它的返回值为undefine,此时构造函数里面的this对象等于全局this对象。this.name其实就是创建一个全局的变量name。在严格模式下,当你补通过new 调用Person构造函数会出现错误;

27、函数声明和函数表达式的区别

//成功
fn()
function fn() {
  console.log("函数声明,全局");
}
//报错
fn1()
var fun1 = function () {
  console.log("函数表达式,局部")
}

28、说一下对变量提升的理解

(1)顾名思义,就是把下面的东西提到上面。在JS中,就是把定义在后面的东东(变量或函数)提升到前面中定义。

var v = 'Hello World';
(function () {
  alert(v); //undefined
  var v = 'I love you';
})()

(2)根据上面变量提升原件以及js的作用域(块级作用域)的分析,得知 上面代码真正变成如下:

var v = 'Hello World';
(function () {
  var v;
  alert(v);
  v = 'I love you';
})()

(3)在我们写js code 的时候,我们有2中写法,一种是函数表达式,另外一种是函数声明方式。我们需要重点注意的是,只有函数声明形式才能被提升。

//成功
function myTest() {
  foo();
  function foo() {
    alert("我来自 foo");
  }
}
myTest();
//失败
function myTest() {
  foo();
  var foo = function foo() {
    alert("我来自 foo");
  }
}
myTest();

29、说一下this几种不同的使用场景

(1)作为构造函数执行,如果函数创建的目的是使用new来调用,并产生一个对象,那么此函数被称为构造器函数;

var Niu = function (string) {
  this.name = string;
};

(2)作为对象属性执行,对象成员方法中的this是对象本身,此时跟其他语言是一致的,但是也有差异,JavaScript中的this到对象的绑定发生在函数调用的时候;

var myObj = {
  value: 0,
  increment: function (inc) {
    this.value += typeof inc === 'number' ? inc : 1;
  }
};
myObj.increment(); //1
myObj.increment(2); //3

(3)作为普通函数执行,以普通方式定义的函数中的this:会被自动绑定到全局对象;

var value = 232;
function toStr() {  
  console.log(this.value);
}

(4)对象方法中闭包函数的this

//在以普通方式定义的函数中的this会被自动绑定到全局对象上,
//大家应该可以看出闭包函数定义也与普通方式无异,因此他也会被绑定到全局对象上。
value = 10;
var closureThis = {
  value: 0,
  acc: function () {
    var helper = function () {
      this.value += 2;
      console.log("this.value : %d", this.value);
    }
    helper();
  }
};
closureThis.acc(); //12
closureThis.acc(); //14

var closureThat = {
  value: 0,
  acc: function () {
    that = this;
    var helper = function () {
      that.value += 2;
      console.log("that.value : %d", that.value);
    }
    helper();
  }
};
closureThat.acc(); // 2
closureThat.acc(); // 4

(5)apply函数的参数this,apply方法允许我们选择一个this值作为第一个参数传递,第二个参数是一个数组,表明可以传递多个参数。

30、如何理解JavaScript作用域?

函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。

function foo() {
  var x = 1;
  return function () {
    alert(x);
  }
};
var bar = foo();
bar(); // 1
var x = 2;
bar(); // 1

31、什么是自由变量?

自由变量就是当前作用域没有定义的变量,即“自由变量”

var a = 100;
function F1() {
  var b = 200;
  function F2() {
    var c = 300;
    //a是自由变量
    console.log(a);
    //b是自由变量
    console.log(b);
    console.log(c);
  }
  F2();
}
F1();

32、this的特点

this要在执行时才能确认值,定义时无法确认。

33、同步和异步的区别是什么?分别举一个同步和异步的例子

同步会阻塞代码执行,而异步不会;alert是同步,setTimeout是异步。

33、一个关于setTimeout的笔试题

//输出结果13542
console.log(1);
setTimeout(function () {
  console.log(2);
}, 100);
console.log(3);
setTimeout(function () {
  console.log(4);
}, 99);
console.log(5)

34、何时需要异步?

在可能发生等待的情况、等待过程中不能像alert一样阻塞程序运行、因此所有的等待的情况都需要异步

35、JavaScript中的异步和单线程

(1)其实,单线程和异步确实不能同时成为一个语言的特性。js选择了成为单线程的语言,所以它本身不可能是异步的,但js的宿主环境(比如浏览器,Node)是多线程的,宿主环境通过某种方式(事件驱动,下文会讲)使得js具备了异步的属性。
(2)js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行,但前端的某些任务是非常耗时的,比如网络请求,定时器和事件监听,如果让他们和别的任务一样,都老老实实的排队等待执行的话,执行效率会非常的低,甚至导致页面的假死。所以,浏览器为这些耗时任务开辟了另外的线程,主要包括http请求线程,浏览器定时触发器,浏览器事件触发线程,这些任务是异步的。

36、使用JavaScript获取当天的日期

function formatDate(dt) {
  if (!dt) {
    dt = new Date();
  }
  var year = dt.getFullYear();
  var month = dt.getMonth() + 1;
  var date = dt.getDate();
  if (month < 10) {
    month = "0" + month;
  }
  if (date < 10) {
    date = "0" + date;
  }
  return year + "-" + month + "-" + date;
}
var dt = new Date();
var formatDate = formatDate(dt);
console.log(formatDate);

37、获取随机数,要求是长度一致的字符串

var random = (Math.random() * 10 + "0000000000").slice(0, 10);
console.log(random);

38、写一个能遍历对象和数组的通用forEach函数

function forEach(obj, fn) {
  if (obj instanceof Array) {
    //准确判断是不是数组
    obj.forEach(function (item, index) {
      fn(index, item);
    })
  } else {
    //不是数组就是对象
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        fn(key, obj[key]);
      }
    }
  }
}
//检测数组
var arr = [1, 2, 3];
//这里顺序换了,为了和对象的遍历格式一致
forEach(arr, function (index, item) {
  console.log(index, item);
});
//检测对象
var obj = {
  x: 100,
  y: 200
};
forEach(obj, function (key, value) {
  console.log(key, value);
})

39、DOM操作的常用API有哪些?

获取DOM节点,以及节点的property和Attribute;获取父节点和子节点;新增节点和删除节点

40、DOM节点的attr和property有何区别?

property只是一个JavaScript对象的属性的修改;Attribute是对html标签属性的修改

41、DOM的本质

浏览器把拿到的HTML代码,结构化一个浏览器能识别并且js可以操作的一个模型而已。

42、手动编写一个ajax,不依赖第三方库

var xmlHttp = new XMLHttpRequest() || new ActiveXObject("Msxml2.XMLHTTP");
xmlHttp.open("提交方式", "提交地址", true);
xmlHttp.onreadystatechange = function () {
  if (xmlHttp.readyState == 4) {
    infoDiv.innerHTML = xmlHttp.responseText;
  }
}
xmlHttp.send();

更多ajax知识,请点击这里

43、什么是跨域?

(1)浏览器有同源策略,不允许ajax访问其他域接口。跨域条件(协议、域名、端口)有一个不同就算是跨域。
(2)可以跨域的三个标签(、、<script src=xxx>)。三个标签的应用场景(用于打点统计,统计网站可能是其他域、<script>可以使用CDN,CDN的也是其他域、<script>可以用于JSOP)。
(3)跨域注意的事项:所有的跨域请求都必须经过信息提供方允许、如果未经过允许即可获取,那是浏览器同源策略出现漏洞。

44、跨域的几种实现方式

(1)通过jsonp跨域:在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。
(2)通过修改document.domain来跨子域:
(3)使用window.name来进行跨域:
(4)使用HTML5中新引进的window.postMessage方法来跨域传送数据:

45、JavaScript实现字符串反转

(1)第一种方法

var str = "abcdef";
console.log(str.split("").reverse().join(""));

(2)第二种方法

var str = "abcdef";
var i = str.length - 1;
for (var x = i; x >= 0; x--) {
  document.write(str.charAt(x));
}

(3)第三种方法

function reverse(str) {
  if (str.length == 0) return null;
  var i = str.length;
  var dstr = "";
  while (--i >= 0) {
    dstr += str.charAt(i);
  }
  return dstr;
}
var str = "abcdef";
str = reverse(str);
document.write(str);

46、ajax中的get和post两种请求方式的异同

(1) get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到;post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
(2)对于get方式,服务器端用Request.QueryString获取变量的值;对于post方式,服务器端用Request.Form获取提交的数据。两种方式的参数都可以用Request来获得。
(3)get传送的数据量较小,不能大于2KB;post传送的数据量较大,一般被默认为不受限制,但理论上,因服务器的不同而异。
(4)get安全性非常低,post安全性较高。
(5)

跟是一样的,也就是说,method为get时action页面后边带的参数列表会被忽视;而跟是不一样的。

47、找出数字数组中最大的元素

var a = [111, 2, 6, 4, 22, 5, 99, 3];
console.log(Math.max.apply(null, a));

48、实现该语法的功能:var a = (5).plus(3).minus(6)

Number.prototype.plus = function (a) {
  return this.valueOf() + a;
}
Number.prototype.minus = function (a) {
  return this.valueOf() - a;
}
var a = (5).plus(3).minus(6);
console.log(a);

49、有一个大数组,var a = [‘1’,’2’,’3’,…];a数组的长度是100,内容填充随机整数的字符串,请先构造此数组a,然后设计一个算法,将其内容去重。

function Random(n) {
  var arr = [];
  for (var i = 0; i < n; i++) {
    arr[i] = parseInt(Math.random() * 100);
  }
  console.log(arr);
  return arr;
}
//使用indexof  这里也可以使用arr2的indexOf
function DeleRepeat1(arr) {
  var arr2 = [];
  var len = arr.length;
  for (var i = 0; i < len; i++) {
    if (arr.indexOf(arr[i]) == i) {
      arr2.push(arr[i])
    }
  }
  return arr2;
}
var arr = Random(100);
console.log(DeleRepeat1(arr));

50、返回只包含数字类型的数组,比如:’abc234koi45jodjnvi789’ –> [234,45,789]

var str = 'abc234koi45jodjnvi789';
function getNum(str) {
  var arr = [];
  str.replace(/(\d+)/g, function (match, data) {
    arr.push(data);
  })
  return arr;
}
console.log(getNum(s
tr));

51、slice数组的浅复制:向数组后添加一个元素,返回原数组不变,返回新数组。

function append(arr, item) {
  var arr2 = [];
  arr2 = arr.slice(0);
  arr2.push(item);
  return arr2;
}
var arr = [1, 2, 3, 4];
console.log(append(arr, 10)); //[1, 2, 3, 4,10]
console.log(arr) //[1, 2, 3, 4]

【解析】
如果定义 var arr2=arr的话,那么arr2指向了arr的引用。那么arr2改变也会伴随着arr改变。 而slice浅复制:arr数组并返回了一个新数组,与原数组没有关系了。

52、实现数组内容增添的函数

function insert(arr, item, index) {
  var arr2 = arr.concat();
  arr2.splice(index, 0, item);
  return arr2;
}
//[1,2,'z',3,4]
console.log(insert([1, 2, 3, 4], 'z', 2));

53、什么是同步?什么是异步

(1)同步:脚本会停留并等待服务器发送回复然后再继续
(2)异步:脚本允许页面继续其进程并处理可能的回复

54、documen.write和 innerHTML的区别是什么?

document.write重绘整个页面;innerHTML可以重绘页面的一部分。

55、介绍JavaScript有哪些内置对象?

(1)数据封装类对象:Object、Array、Boolean、Number 和 String
(2)其他对象:Function、Arguments、Math、Date、RegExp、Error

56、JavaScript的作用域链式什么?

全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节。当需要从局部函数查找某一属性或方法时,如果当前作用域没有找到,就会上溯到上层作用域查找,直至全局函数,这种组织形式就是作用域链。

57、什么是window对象? 什么是document对象?

(1)window对象是指浏览器打开的窗口。
(2)document对象是Documentd对象(HTML 文档对象)的一个只读引用,window对象的一个属性。

58、null,undefined 的区别?

(1)null:表示一个对象是“没有值”的值,也就是值为“空”;
(2)undefined:表示一个变量声明了没有初始化(赋值);
【注意】
在验证null时,一定要使用 === ,因为 == 无法分别 null 和undefined

59、什么是闭包(closure),为什么要用它?

(1)闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。
(2)闭包的特性:

  • 函数内再嵌套函数
  • 内部函数可以引用外层的参数和变量
  • 参数和变量不会被垃圾回收机制回收

60、如何判断一个对象是否属于某个类?

if(a instanceof Person){
  alert('yes');
}

61、new操作符具体干了什么呢?

(1)创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型;
(2)属性和方法被加入到 this 引用的对象中;
(3)新创建的对象由 this 所引用,并且最后隐式的返回 this 。
【栗子】

var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

62、Javascript中,有一个函数,执行时对象查找时,永远不会去查找原型,这个函数是?

(1)javaScript中hasOwnProperty函数方法是返回一个布尔值,指出一个对象是否具有指定名称的属性。此方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身的一个成员。
(2)使用方法:

  • object.hasOwnProperty(proName)
  • 其中参数object是必选项。一个对象的实例。
  • proName是必选项。一个属性名称的字符串值。
  • 如果 object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回 true,反之则返回 false。

63、对JSON 的了解?

(1)JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小,比如:{"age":"12", "name":"back"}
(2)JSON字符串转换为JSON对象:

var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);

(3)JSON对象转换为JSON字符串:

var last=obj.toJSONString();
var last=JSON.stringify(obj);

64、js延迟加载的方式有哪些?

defer和async、动态创建DOM方式(用得最多)、按需异步载入js。

65、异步加载JS的方式有哪些?

(1)defer,只支持IE;
(2)async:
(3)创建script,插入到DOM中,加载完毕后callBack

66、DOM操作——怎样添加、移除、移动、复制、创建和查找节点?

(1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点
(3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性

67、JQuery一个对象可以同时绑定多个事件,这是如何实现的?

(1)多个事件同一个函数:
$("div").on("click mouseover", function(){});
(2)多个事件不同函数

$("div").on({
  click: function(){},
  mouseover: function(){}
})

68、JavaScript中如何检测一个变量是一个String类型或者Array类型?请写出函数实现

var str = "hello";
if (typeof (str) === "string") {
  console.log("str is String");
}
var arr = [];
if (arr instanceof Array) {
  console.log("arr is Array");
}

69、prototype和_proto_的关系是什么

prototype和__proto__都指向原型对象,任意一个函数(包括构造函数)都有一个prototype属性,指向该函数的原型对象,同样任意一个构造函数实例化的对象,都有一个__proto__属性(__proto__并非标准属性,ECMA-262第5版将该属性或指针称为[[Prototype]],可通过Object.getPrototypeOf()标准方法访问该属性),指向构造函数的原型对象。

70、ajax是什么?同步和异步的区别?

(1)ajax是一种无需重新加载整个网页的情况下,能够更新部分网页的技术。
(2)同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。

71、事件委托是什么,举个例子

它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象。

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
      ul li {
        display: block;
        height: 50px;
        width: 100px;
        text-align: center;
        line-height: 50px;
        background-color: #888;
        margin-bottom: 8px;
      }
    </style>
  </head>
  <body>
    <ul id="Inul">
      <li>111</li>
      <li>222</li>
      <li>333</li>
      <li>444</li>
      <li>555</li>
    </ul>
    <script>
      //不使用事件委托
      /*window.onload = function(){
      	var oUL = document.getElementById("Inul");
      	var aLi = oUL.getElementsByTagName("li");
      	for(var i=0;i<aLi.length;i++){
      		aLi[i].onclick = function(){
      			alert(123);
      		}
      	}
      }*/
      //使用事件委托
      window.onload = function () {
        var oUL = document.getElementById("Inul");
        oUL.onclick = function () {
          alert(123);
        }
      }
    </script>
  </body>
</html>

72、判断字符串是否是这样组成的:第一个必须是字母,后面可以是字母、数字和下划线,总长度为5-20

var str = "adfadfa2343243e";
var reg = /^[a-zA-Z]\w{4,19}$/g;
console.log(reg.test(str));

73、编写一个方法,去掉一个数组的重复元素

Array.prototype.methods = function () {
  //定义一个临时数组
  var arr = [];
  //循环遍历当前数组
  for (var i = 0; i < this.length; i++) {
    //判断当前数组下标为i的元素是否已经保存到临时数组
    //如果已经保存,则跳过,佛则将此元素保存到临时数组中
    //没有保存则说明查不到,返回-1
    if (arr.indexOf(this[i]) === -1) {
      arr.push(this[i]);
    }
  }
  return arr;
}
var arry = [2, 3, 5, 6, 6, 7];
console.log(arry.methods());

74、如何实现JavaScript模块化,请至少使用两种方法

(1)立即执行函数(IIFE):可以达到不暴露私有成员的目的。
(2)对象写法:可以把模块写成一个对象,所有的模块成员都放到这个对象里面。

75、编写一个JavaScript函数,该函数有一个n(数字类型),其返回值是一个数组,该数组内是n个随机且不重复的整数,且整数取值范围是[2,32]。

//定义一个函数用来返回整数的取值范围
function getRand(a, b) {
  //ceil向上取整
  var rand = Math.ceil(Math.random() * (b - a) + a);
  return rand;
}
//定义一个函数用来过滤重复的整数
function checkArrIn(rand, arry) {
  if (arry.indexOf(rand) != -1) {
    return true;
  }
  return false;
}
//定义一个执行函数
function fn(n, min, max) {
  var arr = [];
  //判断n是不是一个数字,包含字符串类型的数字
  var isNum = !isNaN(Number(n));
  //判断n的取值是否符合要求
  var isRandOk = (n >= min && n <= max && n <= (max - min)) ? true : false;
  if (n && isRandOk && isNum) {
    for (var i = 0; i < n; i++) {
      var rand = getRand(min, max);
      //假如checkArrIn()返回true,说明有相同元素,那么就重新执行一次
      if (checkArrIn(rand, arr)) {
        i--;
      } else {
        arr.push(rand);
      }
    }
  }
  console.log(arr);
}
//调用函数
fn(10, 2, 32);