(史上最全)Web前端面试试题大全及答案汇总(之篇二JavaScript基础笔试面试题)

1、javascript 的 typeof 返回哪些数据类型

object
number
function
boolean
undefined
string 

2、例举 3 种强制类型转换和 2 种隐式类型转换?

强制(parseInt(),parseFloat(),Number())
隐式(==)
1==”1”//true
null==undefined//true

3、split()和 join() 的区别

前者是切割成数组的形式,
后者是将数组转换成字符串

4、数组方法 pop() push() unshift() shift()

Push()尾部添加 
pop()尾部删除 
Unshift()头部添加 
shift()头部删除

5、事件绑定和普通事件有什么区别

传统事件绑定和符合 W3C 标准的事件绑定有什么区别?

div1.onclick=function(){}; <button onmouseover=””></button> 

1、如果说给同一个元素绑定了两次或者多次相同类型的事件,那么后面的绑定会覆盖前面 的绑定 ;
2、不支持 DOM 事件流 事件捕获阶段目标元素阶段=>事件冒泡阶段

addEventListener
1、 如果说给同一个元素绑定了两次或者多次相同类型的事件,所有的绑定将会依次触发
2、 支持 DOM 事件流
3、 进行事件绑定传参不需要 on 前缀 addEventListener(“click”,function(){},true);//此时的事件就是在事件冒泡阶段执行

ie9 开始,ie11edge:addEventListener
ie9 以前:attachEvent/detachEvent
1、 进行事件类型传参需要带上 on 前缀
2、 这种方式只支持事件冒泡,不支持事件捕获 事件绑定是指把事件注册到具体的元素之上,普通事件指的是可以用来注册的事件

6、IE 和 DOM 事件流的区别

1.执行顺序不一样、
2.参数不一样
3.事件加不加 on
4.this 指向问题
IE9 以前:attachEvent(“onclick”)、detachEvent(“onclick”)
IE9 开始跟 DOM 事件流是一样的,都是 addEventListener

7、IE 和标准下有哪些兼容性的写法

var ev=ev||window.event 
document.documentElement.clientWidth || document.body.clientWidth
var target = ev.srcElement||ev.target

8、call 和 apply 的区别

call 和 apply 相同点:
都是为了用一个本不属于一个对象的方法,让这个对象去执行
    toString.call([],1,2,3)
    toString.apply([],[1,2,3])
    Object.call(this,obj1,obj2,obj3)
    Object.apply(this,arguments)

9、b 继承 a 的方法

考点:继承的多种方式

js继承有5种实现方式:

1、继承第一种方式:对象冒充

 function Parent(username){
    this.username = username;
    this.hello = function(){
      alert(this.username);
    }
  }
  function Child(username,password){
    //通过以下3行实现将Parent的属性和方法追加到Child中,从而实现继承
    //第一步:this.method是作为一个临时的属性,并且指向Parent所指向的对象,
    //第二步:执行this.method方法,即执行Parent所指向的对象函数
    //第三步:销毁this.method属性,即此时Child就已经拥有了Parent的所有属性和方法
    this.method = Parent;
    this.method(username);//最关键的一行
    delete this.method;

    this.password = password;
    this.world = function(){
      alert(this.password);
    }
  }
  var parent = new Parent("zhangsan");
  var child = new Child("lisi","123456");
  parent.hello(); //zhangsan
  child.hello();  //lisi
  child.world();  //123456

2、继承第二种方式:call()方法方式

call方法是Function类中的方法
call方法的第一个参数的值赋值给类(即方法)中出现的this
call方法的第二个参数开始依次赋值给类(即方法)所接受的参数

   function test(str){
                 alert(this.name + " " + str);
     }
    var object = new Object();
    object.name = "zhangsan";
    // 此时,第一个参数值object传递给了test类(即方法)中出现的this,而第二个参数"langsin"则赋值给了test类(即方法)的str
    test.call(object,"langsin"); //zhangsan langsin

    function Parent(username){
        this.username = username;
        this.hello = function(){
            document.write(this.username + "<br>");
    }
  }
  function Child(username,password){
    Parent.call(this,username);

    this.password = password;
    this.world = function(){
      document.write(this.password+ "<br>");
    }
  }
  var parent = new Parent("zhangsan");
  var child = new Child("lisi","123456");
  parent.hello(); //zhangsan
  child.hello();  //lisi
  child.world();  //123456

3、继承的第三种方式:apply()方法方式

apply方法接受2个参数,
A、第一个参数与call方法的第一个参数一样,即赋值给类(即方法)中出现的this
B、第二个参数为数组类型,这个数组中的每个元素依次赋值给类(即方法)所接受的参数

扫描二维码关注公众号,回复: 3080525 查看本文章
  function Parent(username){
    this.username = username;
    this.hello = function(){
      alert(this.username);
    }
  }
  function Child(username,password){
    Parent.apply(this,new Array(username));

    this.password = password;
    this.world = function(){
      alert(this.password);
    }
  }
  var parent = new Parent("zhangsan"); 
  var child = new Child("lisi","123456");
  parent.hello(); //zhangsan
  child.hello();  //lisi
  child.world();  //123456

4、继承的第四种方式:原型链方式

即子类通过prototype将所有在父类中通过prototype追加的属性和方法都追加到Child,从而实现了继承

function Person(){
  }
  Person.prototype.hello = "hello";
  Person.prototype.sayHello = function(){
    alert(this.hello);
  }

  function Child(){
  }
  Child.prototype = new Person();//这行的作用是:将Parent中将所有通过prototype追加的属性和方法都追加到Child,从而实现了继承
  Child.prototype.world = "world";
  Child.prototype.sayWorld = function(){
    alert(this.world);
  }

  var c = new Child();
  c.sayHello();
  c.sayWorld();

5、继承的第五种方式:混合方式

混合了call方式、原型链方式

 function Parent(hello){
    this.hello = hello;
  }
  Parent.prototype.sayHello = function(){
    alert(this.hello);
  }

  function Child(hello,world){
    Parent.call(this,hello);//将父类的属性继承过来
    this.world = world;//新增一些属性
  }

  Child.prototype = new Parent();//将父类的方法继承过来

  Child.prototype.sayWorld = function(){//新增一些方法
    alert(this.world);
  }

  var c = new Child("zhangsan","lisi");
  c.sayHello();
  c.sayWorld();

10、JavaScript this 指针、闭包、作用域

this:指向调用上下文 
闭包:内层作用域可以访问外层作用域的变量 
作用域:定义一个函数就开辟了一个局部作用域,整个 js 执行环境有一个全局作用域

11、事件委托是什么

符合 W3C 标准的事件绑定 addEventLisntener/attachEvent
利用事件冒泡的原理,让自己本身要触发的事件,让他的父元素代替执行!

12、闭包是什么,有什么特性,对页面有什么影响

闭包就是能够读取其他函数内部变量的函数。
闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量
永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数。

13、如何阻止事件冒泡和默认事件

阻止事件冒泡

e. stopPropagation();//标准浏览器
event.canceBubble=true;//ie9 之前

阻止默认事件:
为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止

return false
e.preventDefault();

14、添加 删除 替换 插入到某个接点的方法

obj.appendChild() //添加
obj.insertBefore() //插入。原生的 js 中不提供 insertAfter();
obj.replaceChild()//替换
obj.removeChild()//删除

15、javascript 的本地对象,内置对象和宿主对象

本地对象
Object、Function、Array、String、Number、Date、RegExp、Boolean、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError等可以 用new 实例化的对象
由此得出,JS的本地对象就是ECMA-262中定义的类(引用类型)

内置对象
ECMA-262把内置对象定义为:由ECMAScript提供实现的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现。
这意味着内置对象都是已经实例化好的,不需要我们再进行实例化了,这里我们首先会想到的就是Math对象。
ECMA-262定义的内置对象只有两个:Global和Math。(本地对象和内置对象都是独立于宿主对象,根据定义可以看出来内置对象也是本地对象,在JS中所有的内置对象都是本地对象)。

Math对象是我们经常用到的,但是Global就比较少见了。其实我们经常用到Global对象,只是没有用Global这个名字。

Global对象是一个比较特殊的对象,它是一个全局对象,在程序中只有一个,它的存在伴随着整个程序的生命周期,全局对象不能通过名字来访问,但是它有一个window属性,这个属性指向它本身。

大家也要清楚,在ECMAScript中不存在独立的函数,所有的函数都应该是某个对象的方法。类似于isNaN()、parseInt()、parseFloat()等方法都是Global对象的方法。

宿主对象
宿主对象:由ECMAScript实现的宿主环境提供的对象。
可能这样不是很好理解,上面已经说过了宿主环境包括Web浏览器,所以我们可以这样理解,浏览器提供的对象都是宿主对象。

也可以这样理解,因为本地对象是非宿主环境的对象,那么非本地对象就是宿主对象,即所有的BOM对象和DOM对象都是宿主对象。
那么还有一种对象,那就是我们自己定义的对象,也是宿主对象。

最简单的理解:ECMAScript官方未定义的对象都属于宿主对象。
如浏览器自带的 document,window 等

总结
官方的定义太绕口,还不好理解。说的简单点:
本地对象就是ECMAScript中定义好的对象,如String、Date等,
内置对象是本地对象中比较特殊的一种,它不用实例化,包括Global和Math,
宿主对象就是BOM、DOM和自己定义的对象。

16、document load 和 document ready 的区别

Document.onload 是在结构和样式加载完就执行 js
window.onload:不仅仅要在结构和样式加载完,还要执行完所有的样式、图片这些资源文 件,全部加载完才会触发 window.onload 事件
Document.ready 原生中没有这个方法,jquery 中有 $(document).ready(function)

17、”==”和“===”的不同

前者会自动转换类型
后者不会
1==”1”
null==undefined
===先判断左右两边的数据类型,如果数据类型不一致,直接返回 false
之后才会进行两边值的判断

18、JavaScript的同源策略

详细解答请点击链接进入我的另一篇博客查看(JavaScript的同源策略详解

19、编写一个数组去重的方法

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>去除一个数组中重复的元素</title>
    </head>
    <body>
    <script type="text/javascript">
    /*
     * 方法一:
     */
        var arr = [1, 0, 2, 1, 8, 1, 0, 10, 8];
        var obj = {};
        var temp = [];
        for(var i=0; i<arr.length; i++) {
            if(!obj[arr[i]]) {
                obj[arr[i]] = 1;
                temp.push(arr[i]);
            }
        }
        console.log(temp); //1,0,2,8,10

        /*
         * 方法二:
         */
        var arr2= [1, 0, 2, 1, 8, 1, 0, 10, 8, 9, 11];
        var arr3 = [];
        for(var i=0; i<arr2.length; i++) {
        //indexOf()方法从数组的开头(位 置 0)开始向后查找,返回索引号
        //若未找到则返回-1
            if((arr3.indexOf(arr2[i])) < 0) {
                arr3.push(arr2[i]);
            }
        }
        console.log(arr3);//1,0,2,8,10,9,11
        /*
         * 方法三:
         */
        //filter():对数组中的每一项运行给定函数,返回该函数会返回 true的项组成的数组。 
        var arr4 = [0, 10, 22, 0, 10, 1, 2, 3, 1];
        var arr5 = arr4.filter(function(element, index, arr4) {
            return arr4.indexOf(element) == index;
        });
        console.log(arr5); //0,10,22,1,2,3
    </script>
    </body>
</html>

21、JavaScript 的数据类型都有什么?

基本数据类型:String,Boolean,number,undefined,object,Null

引用数据类型:Object(Array,Date,RegExp,Function)

那么问题来了,如何判断某变量是否为数组数据类型?

方法一.判断其是否具有“数组性质”,如 slice()方法。可自己给该变量定义 slice 方法,
故有时会失效

方法二.obj instanceof Array 在某些 IE 版本中不正确

方法三.方法一二皆有漏洞,在 ECMA Script5 中定义了新方法 Array.isArray(), 保证其兼
容性,最好的方法如下:

toString.call(18);//”[object Number]”
toString.call(“”);//”[object String]”

解析这种简单的数据类型直接通过 typeof 就可以直接判断

toString.call 常用于判断数组、正则这些复杂类型
toString.call(/[0-9]{10}/)//”[object RegExp]”
if(typeof Array.isArray==="undefined"){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==="[object Array]"
};
}

22、已知 ID 的 Input 输入框,希望获取这个输入框的输入值,怎么做?(不使 用第三方框架)

document.getElementById(“ID”).value

23、希望获取到页面中所有的 checkbox 怎么做?(不使用第三方框架)

var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];//返回的所有的 checkbox
var len = domList.length; //缓存到局部变量
while (len--) { //使用 while 的效率会比 for 循环更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}

24、设置一个已知 ID 的 DIV 的 html 内容为 xxxx,字体颜色设置为黑色(不使用 第三方框架)

var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”
dom.style.color = “#000

25、当一个 DOM 节点被点击时候,我们希望能够执行一个函数,应该怎么做?

直接在 DOM 里绑定事件:<div onclick=”test()”></div>

在 JS 里通过 onclick 绑定:xxx.onclick = test

通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)

那么问题来了,Javascript 的事件流模型都有什么?

“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的

“DOM 事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡

26、看下列代码输出为何?解释原因。

var a;
alert(typeof a); // “undefined” 
//alert(b); // 报错 
b=10; 
alert(typeof b);//”number”

解释:Undefined 是一个只有一个值的数据类型,这个值就是“undefined”,在使用 var
声明变量但并未对其赋值进行初始化时,这个变量的值就是 undefined。而 b 由于未声明将
报错。注意未申明的变量和声明了未赋值的是不一样的。

undefined 会在以下三种情况下产生:

  • 1、 一个变量定义了却没有被赋值
  • 2、 想要获取一个对象上不存在的属性或者方法:
  • 3、 一个数组中没有被赋值的元素

注意区分 undefined 跟 not defnied(语法错误)是不一样的

27、看下列代码,输出什么?解释原因。

var a = null;
alert(typeof a); //object

解释:null 是一个只有一个值的数据类型,这个值就是 null。表示一个空指针对象,所以
用 typeof 检测会返回”object”。

28、看下列代码,输出什么?解释原因。

var undefined;//此时 undefined 这个变量的值是 undefined
undefined == null; // true
1 == true; // true

此时会把布尔类型的值转换为数字类型

true=1 false=0
2 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true 
  • undefined 与 null 相等,但不恒等(===)
  • 一个是 number 一个是 string 时,会尝试将 string 转换为 number
  • 尝试将 boolean 转换为 number,0 或 1
  • 尝试将 Object 转换成 number 或 string,取决于另外一个对比量的类型

所以,对于 0、空字符串的判断,建议使用 “===” 。“===”会先判断两边的值类
型,类型不匹配时为 false。

那么问题来了,看下面的代码,输出什么,foo 的值为什么?

var foo = "11"+2-"1";
console.log(foo);//111
console.log(typeof foo);

执行完后 foo 的值为 111,foo 的类型为 number。

29、看代码给答案。

var a = new Object();
a.value = 1;
b = a; //{value:1}
b.value = 2;
alert(a.value);//2

答案:2(考察引用数据类型细节)

30 、 已 知 数 组 var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert 出”This is Baidu Campus”。

答案:

alert(stringArray.join(“ ”))

31、已知有字符串 foo=”get-element-by-id”,写一个 function 将其转化成驼峰表示法”:getElementById”。

function combo(msg){
var arr=msg.split("-");//[get,element,by,id]
for(var i=1;i<arr.length;i++){
   arr[i]=arr[i].charAt(0).toUpperCase()+arr[i].substr(1,arr[i].length-1);//Element
}
msg=arr.join("");//msg=” getElementById”
return msg;
}

(考察基础 API)

32、输出今天的日期,以 YYYY-MM-DD 的方式,比如今天是 2014 年 9 月 26 日, 则输出 2014-09-26

var d = new Date();
// 获取年,getFullYear()返回 4 位的数字
var year = d.getFullYear();
// 获取月,月份比较特殊,0 是 1 月,11 是 12 月
var month = d.getMonth() + 1;
// 变成两位
month = month < 10 ? '0' + month : month;
// 获取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
alert(year + '-' + month + '-' + day);

33、将字符串”<tr><td>{$id}</td><td>{$name}</td></tr>”中的{$id}替换 成 10,{$name}替换成 Tony (使用正则表达式)

答案:

"<tr><td>{$id}</td><td>{$name}</td></tr>".replace(/{\$id}/g, '10').replace(/{\$name}/g, 'Tony');

34、为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写 一个函数 escapeHtml,将<, >, &, \进行转义

function escapeHtml(str) {
//[<>”&]:中括号中字符只要其中的一个出现就代表满足条件
//给 replace 第二个参数传递一个回调函数,回调函数中参数就是匹配结果,如果匹配不到就是null
    return str.replace(/[<>"&]/g, function(match) {
        switch (match) {
            case "<":
            return "&lt;";
            case ">":
            return "&gt;";
            case "&":
            return "&amp;";
            case '\"':
            return "&quot;";
          }
      });
}

35、foo=foo||bar ,这行代码是什么意思?为什么要这样写?

这种写法称之为短路表达式

意思为:if(!foo) foo = bar; //如果 foo 存在,值不变,否则把 bar 的值赋给 foo。

短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要
最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。

注意 if 条件的真假判定,记住以下是 false 的情况:
空字符串、false、undefined、null、0

36、看下列代码,将会输出什么?(变量声明提升)

var foo = 1;
function(){
    console.log(foo); //undefined
    var foo = 2;
    console.log(foo); //2
}

答案:输出 undefined 和 2。上面代码相当于:

var foo = 1;
function(){
    var foo;
    console.log(foo); //undefined
    foo = 2;
    console.log(foo); // 2;
}

函数声明与变量声明会被 JavaScript 引擎隐式地提升到当前作用域的顶部,但是只提升名
称不会提升赋值部分。

37、用 js 实现随机选取 10–100 之间的 10 个数字,存入一个数组,并排序。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
        /*
         * 随机选取[10, 100]内的10个数
         *并排序
         * Math.floor(num); 取得num整数部分
         * Math.ceil(num); 取得大于等于num的最小整数
         * Math.round(num); num四舍五入后的整数
         */
        var pushArray = []; //存放取出的数
        //产生一个10到100之间的数
        function getRandom(start, end) {
            var choice = end - start + 1;
            return Math.floor(Math.random() * choice + start);
        }
        //Math.random()就是获取 0-1 之间的随机数(永远获取不到 1)
        for(var i=0; i<10; i++) {
            var result = getRandom(10, 100);
            pushArray.push(result);
        }
        pushArray.sort();
        console.log(pushArray); //12,19,21,28,34,39,44,54,65,86
        </script> 

    </body>
</html>

38、把两个数组合并,并删除第二个元素。

var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1);  //splice() 方法用于插入、删除或替换数组的元素。

splice()方法如下所示:

//splice()方法
/*
 * 删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数
 * 会影响原始数组
 */
var fruits = ["apple", "mango", "banana", "pear"];
var fruit1 = fruits.splice(0, 2);
document.write(fruits + "<br>"); //banana,pear
document.write(fruit1); //返回删除的项apple,mango
document.write("<br>");
/*
 * 插入:可以向指定位置插入任意数量的项,只需提供 3个参数:
 * 起始位置、0(要删除的项数) 和要插入的项
 */
var fruit2 = ["apple", "mango", "banana", "pear"];
var fruit3 = fruit2.splice(2, 0, "strawberry", "lalala");
document.write(fruit2 + "<br>");//apple,mango,strawberry,lalala,banana,pear
document.write(fruit3 + "<br>");//未删除项,所以返回空数组
/*
 * 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,
 * 只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。
 * 插入的项数不必与删除的项数相等。
 */
var fruit4 = ["apple", "mango", "banana", "pear"];
var fruit5 = fruit4.splice(1, 2, "aaa", "bbb", "ccc");
document.write("<br>" + fruit4 + "<br>");//apple,aaa,bbb,ccc,pear
document.write(fruit5);  // 返回删除的项mango,banana

39、怎样添加、移除、移动、复制、创建和查找节点

详细讲解请见本人另一篇博客((完全详解)JavaScript 添加、复制、移除、移动、创建和查找节点)】

40、有这样一个 URL: http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e, 请写一段 JS 程序提取 URL 中的各个 GET 参数(参数名和参数个数不确定),将其 按 key-value 形式返回到一个 json 结构中,如{a:’ 1′, b:’ 2′, c:” , d:’ xxx’, e:undefined}。

截取问号后的字符串,按‘&’间隔拆分,再按‘=’拆分,再分情况判断。

var url='http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e';
function nameAndValue(url){
   url=url.split('?')[1];
   var group=url.split('&');
   var res={};
   for(var i=0;i<group.length;i++){
       start=group[i].indexOf('=');
       if(start!=-1){
           name=group[i].slice(0,start);
           value=group[i].slice(start+1,group[i].length);
           res[name]=value;
       }else{
           res[group[i]]=undefined;
       }
   }
   for(var key in res) {
    document.write(key + ":" + " " + res[key]);
    document.write("<br>");
}
}
nameAndValue(url);

结果:

a: 1
b: 2
c:
d: xxx
e: undefined

41、正则表达式构造函数 var reg=new RegExp(“xxx”)与正则表达字面量 var reg=//有什么不同?匹配邮箱的正则表达式?

答案:当使用 RegExp()构造函数的时候,不仅需要转义引号(即\”表示”),并且还需要
双反斜杠(即\表示一个\)。
使用正则表达字面量的效率更高。

邮箱的正则匹配:

var regMail = /^[A-Za-z\d]+[A-Za-z\d\-_\.]*@([A-Za-z\d]+[A-Za-z\d\-]*\.)+[A-Za-z]{2,4}$/;

24.看下面代码,给出输出结果。

for(var i=1;i<=3;i++){
    setTimeout(function(){
    console.log(i);
    }, 0);
};

答案:4 4 4。
原因: Javascript 事件处理器在线程空闲之前不会运行。
追问,如何让上述代码输出 1 2 3?

for(var i=1;i<=3;i++){
    setTimeout((function(a){ //改成立即执行函数
    console.log(a);
    })(i), 0);
};

1 //输出
2
3

42、写一个 function,清除字符串前后的空格。(兼容所有浏览器)

使用自带接口 trim(),考虑兼容性:

if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+/, "").replace(/\s+$/,"");
//\s 匹配空白字符:回车、换行、制表符 tab 空格
}
}
// test the function
var str = " \t\n test string ".trim();
alert(str == "test string"); // alerts "true"

猜你喜欢

转载自blog.csdn.net/qq_36595013/article/details/82428441