整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

2022最新前端 JS 笔试100道题

2022最新前端 JS 笔试100道题

S基础

js概念与类型检测

  1. 以下不属于 typeof 运算符返回值的是?
A. "string"
B. "function"
C. "object"
D. "null"
  1. 执行以下代码,错误的输出结果是
A. 输入:typeof {"x":1} 输出:"object" 
B. 输入:typeof 1 输出:"number" 
C. 输入:typeof [{x:1}] 输出:"array" 
D. 输入:typeof NaN 输出:"number"
  1. 可以用typeof来判断的基本类型有
A. undefined
B. null
C. array
D. object
  1. 以下不属于JavaScript基本数据类型的是:
A. Boolean
B. undefined
C. Symbol
D. Array
  1. 以下关于JavaScript中数据类型的说法错误的是()
A. 数据类型分为基本数据类型和引用数据类型
B. JavaScript一共有8种数据类型
C. Object是引用数据类型,且只存储于堆(heap)中
D. BigInt是可以表示任意精度整数的基本数据类型,存储于栈(stack)中

答案

DCADC

逻辑判断

  1. 请选择结果为ture的表达式?
A. null instanceof Object
B. null===undefined
C. null==undefined
D. NaN==NaN
  1. 下列代码结果为 true 的是?
A. Symbol.for('a')===Symbol.for('a')
B. Symbol('a')===Symbol('a')
C. NaN===NaN
D. {}==={}
  1. 根据如下变量,下列表达式中返回值为true的是
var a=1;
var b=[];
var c='';
var d=true;
A. (a || b)===true
B. (b && c)===true
C. (c && d)===true
D. (d || a)===true
  1. 1==true的返回值是true,这句话是否正确?
A. T
B. F
  1. 下面代码输出为true的是?
A. console.log([]===[]);
B. console.log(undefined==0);
C. console.log(undefined==false);
D. console.log(false=='');
  1. 浏览器环境下,以下打印结果为true的是
A. console.log("12"===12)
B. console.log (NaN===NaN)
C. console.log (typeof(null)===typeof(window))
D. console.log ([1,2,3]===[1,2,3])

注意浏览器环境与node环境的差别,比如C选项

  1. 以下表达式,正确的是
A. Number('a')==Number('a')
B. -1==true
C. 3 + '2'===5
D. ![]==''

答案

CADADCD

Math

  1. 如何把 7.25 四舍五入为最接近的整数
A. Math.round(7.25)
B. Math.ceil(7.25)
C. round(7.25)
D. Math.rnd(7.25)
  1. 下面哪个选项可以产生0<=num<=10的随机整数
A. Math.floor(Math.random()*6)
B. Math.floor(Math.random()*10)
C. Math.floor(Math.random()*11)
D. Math.ceil(Math.random()*10)
  1. 以下( )表达式产生一个0~7之间(含0,7)的随机整数
A. Math.floor(Math.random()*6)
B. Math.floor(Math.random()*7)
C. Math. floor(Math.random()*8)

答案

A CD(注意D) C

字符串

  1. split() 方法用于把一个字符串分割成字符串数组。
A. T
B. F
  1. String对象的哪个方法可以寻找子字符串并返回该子字符串位置
A. match()
B. indexOf()
C. search()
D. concat()

答案

A BC

JSON

  1. 下面哪一个是JSON数据?
A. {name:"xiaoming",age,"student"}
B. {"name":"xiaoming","age":"student"}
C. {"xiaoming","student"}
D. ["xiaoming","student"]
  1. 下面分别使用 JSON.stringify 方法,返回值 res 分别是
const fn=function(){}
const res=JSON.stringify(fn)
const num=123
const res=JSON.stringify(num)
const res=JSON.stringify(NaN)
const b=true
const res=JSON.stringify(b)
A. 'function'、'123'、'NaN'、'true'
B. undefined、'123'、undefined、'true'
C. undefined、'123'、'null'、'true'
D. undefined、'123'、'null'、undefined

答案

BC

数组

  1. js数组中不会改变原有数组的方法是()
A. push
B. concat
C. sort
D. shift
  1. 下列哪种数组的方法不会修改数组本身
A. slice
B. splice
C. sort
D. unshift
  1. JavaScript中需要往数组末尾处添加一个元素,应该使用以下哪个方法:
A. push
B. pop
C. shift
D. unshift
  1. 以下js操作Array的方法中不能添加元素的是:
A. push
B. pop
C. unshift
D. splice
  1. 数组以下哪个方法会影响原数组?
A. concat
B. splice
C. slice
D. join
  1. JavaScript中,下列哪一个Array的方法的返回值类型和其他不同
A. concat
B. shift
C. filter
D. map
  1. 如下的Array.prototype上的方法中,那个方法不会改变原有的数组?
A. push
B. slice
C. splice
D. sort
  1. 对于一个数字组成的数组 nums,现在需要执行在不改动 nums 的基础上去重操作,返回一个新的无重复元素的数组,以下几段代码能完成这一操作的是()
// (1)
const newNums=Array.from(new Set(nums))
// (2)
const newNums=nums.filter((n, i)=> {
    return nums.indexOf(n)===i
})
// (3)
const newNums=nums.forEach((n, i)=> {
    return nums.indexOf(n)===i
})
// (4)
const newNums=nums.reduce((acc, n, i)=> {
    return [].concat(acc, nums.indexOf(n)===i ? n : []
)
})
A. (1)、(2)、(3)、(4)
B. (1)、(3)、(4)
C. (1)、(2)、(4)
D. (1)、(4)

答案

BAABB
BBC

正则

  1. 正则表达式 ^d+[^d]+ 能匹配下列哪个字符串?
A. 123
B. 123a
C. d123
D. 123def
  1. 下面哪个不是RegExp对象的方法
A. test
B. match
C. exec
D. compile
  1. 以下哪项可以去除变量str中的所有空格
A. str.replace(`/\s*/g,""`)
B. str.replace(`/^\s|\s$/g,""`)
C. str.replace(`/^\s*/, ""`)
D. str.replace(`/(\s*$)/g, ""`)

答案

CBA

其他

  1. 下列函数哪个不是JavaScript的全局函数
A. encodeURI
B. parseFloat
C. round
D. eval
  1. 编写高性能JavaScript,以下描述错误的是
A. 遵循严格模式:"use strict"
B. 将js脚本放在页面顶部,加快渲染页面
C. 将js脚本成组打包,减少请求,尽量减少使用闭包
D. 使用非阻塞方式下载js脚本,最小化重绘(repaint)和回流(reflow)
  1. 有关JavaScript中系统方法的描述,错误的是?
A. parseFloat方法:该方法将一个字符串转换成对应的小数
B. isNaN方法:该方法用于检测参数是否为数值型,如果是,返回true,否则,返回false。
C. escape方法: 该方法返回对一个字符串编码后的结果字符串
D. eval方法:该方法将某个参数字符串作为一个JavaScript执行题
  1. 下面列出的浏览器,无webkit内核的是()
A. chrome
B. Safari
C. 搜狗浏览器
D. Firefox
  1. 下列代码哪个能够实现获取形式为 2017-08-01 形式的日期( )?
// A
var formatDate=getDate()
// B
var formatDate=new Date()
// C
var formatDate=function (date) {
    var y=date.getFullYear();
    var m=date.getMonth() + 1;
    
    var d=date.getDate();
    return y + '-' + m + '-' + d;
};
// D
var formatDate=function (date) {
    var y=date.getFullYear();
    var m=date.getMonth() + 1;
    m=m < 10 ? '0' + m : m;
    var d=date.getDate();
    d=d < 10 ? ('0' + d) : d;
    return y + '-' + m + '-' + d;
};
  1. 下面哪一项不能最小化重绘(repaint)和回流(reflow)
A. 需要对元素进行复杂的操作时,可以先隐藏(display:"none"),操作完成后再显示
B. 需要创建多个DOM节点时,使用DocumentFragment创建完后一次性的加入document
C. 尽量避免用table布局(table元素一旦触发回流就会导致table里所有的其它元素回流)
D. 尽量不要使用 css 属性简写,如:用border-width, border-style, border-color代替border

答案

CBBDDD

JS深入

this

  1. 下列哪种方法不能改变this指向()
A. eval
B. apply
C. bind
D. call
  1. 在JavaScript中下面选项关于this描述正确的是
A. 在使用new实例化对象时, this指向这个实例对象
B. 将对象的方法赋值给变量A。执行A()时 该方法中的this指向这个对象。 
C. 在函数定义时,this指向全局变量
D. 在浏览器下的全局范围内,this指向全局对象
  1. 下面有关JavaScript中call和apply方法的描述,错误的是?
A. call与apply都属于Function.prototype的一个方法,所以每个function实例都有call、apply属性
B. 两者传递的参数不同,call函数第一个参数都是要传入给当前对象的对象,apply不是
C. apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入
D. call传入的则是直接的参数列表。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

答案

AAB

作用域(闭包)

  1. 内存泄漏是 javascript 代码中必须尽量避免的,以下几段代码可能会引起内存泄漏的有()
// (1)
function getName() {
    name='javascript'
}
getName()
// (2)
const elements={
    button: document.getElementById('button')
};
function removeButton() {
    document.body.removeChild(elements.button);
}
removeButton()
// (3)
let timer=setInterval(()=> {
    const node=document.querySelector('#node') 
    if(node) {
        clearInterval(timer)
    }
}, 1000);
A. (1)、(2)、(3)
B. (2)、(3)
C. (1)、(3)
D. (1)、(2)
  1. 那个操作不会造成内存泄露
A. 没有清理的DOM元素引用
B. 被遗忘的定时器
C. 事件侦听没有移除
D. 局部变量不用时,没有设为null
  1. 下列关于闭包理解错误的是
A. 增加一定的内存消耗
B. 使用不当可能会导致内存泄漏
C. 可以使用闭包模拟私有方法
D. 闭包会改动对象的原型链

答案

DDD

原型与继承

  1. JavaScript实现继承的方式,不正确的是:
A. 原型链继承
B. 构造函数继承
C. 组合继承
D. 关联继承
  1. 所有对象都有原型
A. T
B. F
  1. 以下关于原型链的描述正确的是:
A. 通过原型链继承的属性和对象自己定义的属性等效
B. 通过原型链可以模拟对象的私有属性
C. 在对象上访问不存在的属性时,会依次遍历整条原型链
D. 所有 JavaScript 中的对象都是位于原型链顶端的 `Object` 的实例

答案

DBC

其他

  1. 以下不属于前端数据存储方式的是?
A. jsonp
B. cookie
C. localStorage
D. sessionStorage

答案

A

DOM题

事件流

  1. 将A元素拖拽并放置到B元素中,B元素需要做哪项操作()?
A. event.preventDefault()
B. event.prevent()
C. event.drag()
D. event.drop()
  1. 以下不支持冒泡的鼠标事件为( )?
A. mouseover
B. click
C. mouseleave
D. mousemove
  1. 在javascript中,用于阻止默认事件的默认操作的方法是
A. stopDeafault()
B. stopPropagation()
C. preventDefault()
D. preventDefaultEven()
  1. 事件传播的三个阶段是什么
目标 -> 捕获 -> 冒泡
冒泡 -> 目标 -> 捕获
目标 -> 冒泡 -> 捕获
捕获 -> 目标 -> 冒泡
  1. 下面有关 javascript 常见事件的触发情况,描述错误的是?
A. onchange:用户改变域的内容
B. onkeypress:某个键盘的键被按下或按住
C. onmousedown:某个鼠标按键被按下
D. onblur:元素获得焦点

答案

ACCDD

DOM遍历

  1. 下列哪项不属于DOM查找节点的属性()?
A. parentObj.firstChild
B. parentObj.children
C. neborNode.previousSibling
D. neborNode.siblings
  1. DOM中,给父节点添加子节点的正确方法为()?
A. appendChild(parentNode,newNode);
B. append(parentNode,newNode);
C. parentNode.append(newNode);
D. parentNode.appendChild(newNode);
  1. JavaScript中document.getElementById()返回值的类型为?
A. Array
B. Object
C. String
D. Function
  1. DOM中,给父节点添加子节点的正确方法为()?
A. appendChild(parentNode,newNode);
B. append(parentNode,newNode);
C. parentNode.append(newNode);
D. parentNode.appendChild(newNode);

答案

DDBD

其他

  1. DOM元素的以下属性改变会导致重排(reflows)的是
outline
visiblity
font-size
background-color

答案

C

BOM题

  1. setInterval(updateClock,60)的含义是( )?
A. 每隔60秒调用一次updateClock()
B. 每隔60毫秒调用一次updateClock()
C. 每隔60分钟调用一次updateClock()
D. 每分钟调用60次updateClock()
  1. 使用方法( )可以获取到地理位置所在的经纬度?
A. Geolocation.watchPosition()
B. Geolocation.getCurrentPosition()
C. Geolocation.getPosition()
D. Geolocation.Position()
  1. setInterval("alert('welcome');",1000);这段代码的意思是
A. 等待1000秒后,再弹出一个对话框
B. 等待1秒钟后弹出一个对话框
C. 每隔一秒钟弹出一个对话框
D. 语句报错,语法有问题

答案

BBC

ES6题

箭头函数

  1. 下列对js箭头函数描述错误的是()
A. 箭头函数没有原型属性
B. 箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值
C. 箭头函数可以作为构造函数,使用new
D. 箭头函数不绑定arguments,取而代之用rest参数解决
  1. 关于箭头函数下列说法错误的一项是:
A. 函数体内this的指向是定义时所在的对象,而不是使用时所在的对象
B. 箭头函数内不能使用arguments对象
C. 箭头函数不能使用yield命令
D. 可以使用new创建一个箭头函数的实例

答案

CD

promise

  1. 关于将 Promise.all 和 Promise.race 传入空数组的两段代码的输出结果说法正确的是:
Promise.all([]).then((res)=> {
    console.log('all');
});
Promise.race([]).then((res)=> {
    console.log('race');
});
A. all 和 race 都会被输出
B. all 和 race 都不会被输出
C. all 会被输出,而 race 不会被输出
D. all 不会被输出,race 会被输出
  1. 以下方案中,不是用于解决回调陷阱的的是:
A. Promise
B. Generator
C. async
D. Proxy
  1. 在 ECMAScript6 中,不属于promise的状态是:
A. Pending
B. Pause
C. Fulfilled
D. Rejected

答案

CDB

解构赋值

  1. 关于ES6解构表达式,描述正确的是()
let [a,b, c,d, e]="hello"; 
A. e="hello";
B. 其它都为undefined
C. 当中 a="h", b="e";
D. 语法报错

答案

C

多选题

JS基础

  1. 下面哪些数组方法会改变原数组
A. push 
B. concat 
C. splice 
D. map
  1. 下面可以声明数字的js代码是
A. const a=0xa1
B. const a=076
C. const a=0b21
D. const a=7e2
  1. 以下属于操作符 typeof 的返回值的是:
(1)function
(2) object
(3) null
(4) array
(5) NaN
(6) bigint
(7) regexp
(8) undefined
A. (1)、(2)、(3)、(4)、(5)、(6)、(7)、(8)
B. (1)、(2)、(3)、(8)
C. (1)、(2)、(8)
D. (1)、(2)、(6)、(8)
  1. 以下()结果等于字符串string
A. typeof 'string'
B. String('string').toString()
C. 'string'.split('').sort().join('')
D. (function(string){return string})('string')
E. JSON.parse('{"string":"string"}').string
  1. 下面的等式成立的是?
A. parseInt(46.8) `==` parseFloat(46.8)
B. NaN `!==` NaN
C. isNaN('abc') `==` NaN
D. typeof NaN `===` 'number'
  1. 以下哪些选项可以将集合A转化为数组?
A. Array.from(A)
B. [].slice.apply(A)
C. [...A]
D. [].map.call(A, o=> o)
  1. 下列结果返回 true 的是
A. null==undefined
B. null===undefined
C. null===null
D. NaN==null
E. NaN===NaN
F. Infinity + 1 !==Infinity

答案

AC ABD D ABDE BD ABCD AC

JS深入

  1. 关于以下代码,说法正确的有哪些?

function Person() { } var person=new Person();

A. 每一个原型都有一个constructor属性指向关联的构造函数。
B. 每一个对象都有一个prototype属性。
C. Object.getPrototypeOf(person)===Person.prototype
D. person.constructor===Person
  1. 下列在 JS 时间循环机制中属于微任务(microTask)的是?
A. process.nextTick
B. promise
C. setTimeout
D. setInterval

答案

ACD AB

ES6

  1. 以下关于let和const的说法中正确的是:
A. let声明的变量值和类型都可以改变
B. const声明的常量不可以改变
C. 两者都不存在变量提升,同时存在暂时性死区,只能在声明的位置后面使用
D. const可以先声明再初始化,可以后赋值
  1. 下面关于Promise说法正确的是(注意“返回结果”的意思包含成功或者失败)
A. Promise.all在所有给定的promise都fulfilled后才返回结果
B. Promise.race在给定的promise中,某个fulfilled后才返回结果
C. promise.then的回调函数中,可以返回一个新的promise
D. 对于一个向后台获取数据已经产生结果的promise:p1,再次调用p1.then,不会去重新发起请求获取数据

答案

ABC CD

DOM

  1. 下列关于使用 JS 修改元素样式的代码,正确的有哪些?
document.body.style.['background-color']='#fff'
document.body.style.setProperty('background-color', '#fff')
document.body.style='background-color': #fff'
document.body.style.fontSize='14px'
  1. 下列方法可用于阻止事件冒泡的有
A. event.cancelBubble=true;
B. event.stopPropagation();
C. event.preventDefault();
D. return false;

答案

BCD ABD

填空题

类型检测

  1. 在JavaScript中,有var arr=[]; typeof arr的结果为
  2. 以下使用 typeof 操作符的代码的输出结果为
var x=typeof x
var res=typeof typeof x;
console.log(x, res)
  1. [typeof null, null instanceof Object]的结果是什么
  2. typeof typeof 0
  3. JavaScript的typeof运算符的可能结果为array?解释为什么
  4. 下面代码的输出结果是多少?
var arr=[];
console.log(typeof arr, Object.prototype.toString.call(arr));
  1. console.log(Object.prototype.toString.call(undefined))

类型转换

  1. 表达式 "2"+3+4 的值为
  2. console.log('5' + 3, 5 + '3')
  3. var a=parseInt(“111办公室”);alert(a);
  4. ["0x1", "0x2", "0x3"].map(parseInt) 的结果
  5. 在js中执行 1+'1'的结果是?
  6. 在js中执行 parseInt('77',40)的结果是?

逻辑判断

  1. 请给出 [5<6<3,3<2<4] 代码的运行结果
  2. (2<3)||(3<2) 表达式将返回值为
  3. console.log(true||false&&false, true&&false||true)的输出结果是?

其他

  1. 1 + - + + + - + 1 的结果是
  2. [ 'a', ,'b', ,].length 的结果是

程序题

JS基础

  1. 下面两个程序的输出结果分别是?
// case 1
function showCase(value) {
    switch(value) {
    case 'A':
        console.log('Case A');
        break;
    case 'B':
        console.log('Case B');
        break;
    case undefined:
        console.log('Case undefined');
        break;
    default:
        console.log('Case default');
    }
}
showCase(new String('A'));
// case 2
function showCase(value) {
    switch(value) {
    case 'A':
        console.log('Case A');
        break;
    case 'B':
        console.log('Case B');
        break;
    case undefined:
        console.log('Case undefined');
        break;
    default:
        console.log('Case default');
    }
}
showCase(String('A'));
  1. p标签的的内容会显示什么?
<html>
    <body>
        <p id="demo"></p>
        <script type="text/javascript">
            var x=10;
            var y="10";
            document.getElementById("demo").innerHTML=Boolean(x==y);
        </script>
    </body>
</html>
  1. document.write的结果会是什么?
function funcA(x){
    var temp=4;

    function funcB(y){
        document.write( ++x + y + (temp--));
    }

    funcB(5);
}

funcA(6)
  1. alert的结果会是多少
var varArr=function(i,j,str) {  
    return j==0 ? str : varArr(i,--j,(str+=" " + i[j]));
}
var arr=new Array('apple','orange','peach','lime');
var str=varArr(arr,arr.length,"");
alert(str);
  1. 下面程序的输出结果是多少?
function greetingMaker(greeting) { 
    function addName(name) {    
        greeting=greeting.split(' ').reverse().join("-");
        return greeting + " " + name;
    }
    
    return addName;
}

var daytimeGreeting=greetingMaker("Good Day to you");
alert(daytimeGreeting(name)); 
  1. 下面程序的输出结果是多少?
String.prototype.GetNum=function() { 
    var regEx=/[^\d]/g; 
    return this.replace(regEx, ''); 
};

var str="a1b2c3";
str=str.GetNum();
alert(str);
  1. 下面程序的输出结果是多少?
function sum(a, b) {
  return a + b;
}
sum(1, "2");
  1. 下面程序的输出结果是多少?
var str="我非常喜欢编程";
str.length=3;
console.log(str);
  1. 下面程序的输出结果是多少?
let number=0;
console.log(number++);
console.log(++number);
console.log(number);
  1. 下面程序的输出结果是多少?
function nums(a, b) {
    if (a > b)
        console.log('a is bigger')
    else 
        console.log('b is bigger')
    return a + b
}
console.log(nums(4, 2))
console.log(nums(1, 2))
  1. 下面程序输出结果是多少?
function side(arr) {
    arr[0]=arr[2];
}
function func1(a, b, c=3) {
    c=10;
    side(arguments);
    console.log(a + b + c);
}
function func2(a, b, c) {
    c=10;
    side(arguments);
    console.log(a + b + c);
}
func1(1, 1, 1);
func2(1, 1, 1);
  1. 下面代码的输出结果是什么?
var a=3;
var b=new Number(3);
var c=3;

console.log(a==b);
console.log(a===b);
console.log(b===c);

  1. 执行下列语句后,a.length的值为?
var a=[];
a.push(1, 2);
a.shift(3, 4);
a.concat([5, 6]);
a.splice(0, 1, 2);
  1. 下面这几段代码分别输出结果是多少?为什么?
var a={}, b='123', c=123;
a[b]='b';
a[c]='c';
console.log(a[b]);
// example 2
var a={}, b=Symbol('123'), c=Symbol('123');
a[b]='b';
a[c]='c';
console.log(a[b]);
// example 3
var a={}, b={key:'123'}, c={key:'456'};
a[b]='b';
a[c]='c';
console.log(a[b]);
  1. 下面每项的返回值是什么?为什么?
null==undefined
0.1 + 0.2==0.3
typeof NaN
typeof Function
typeof Object
typeof {}
'a' + 1
'a' - 1
Function instanceof Object
Object instanceof Function
  1. 下面程序的输出结果是多少?
var array=[]
for(var i=0; i < 3; i++) {
    array.push(()=> i)
}
var newArray=array.map(el=> el())
console.log(newArray)
  1. 下面程序的输出结果是多少?
 function a(m, n) {
        var b=function (l) {
            return l <=m ? l * b(l + 1) : 1;
        }

        return b(m - n + 1);
    }

console.log(a(4, 2));
  1. 下面程序的输出结果是多少?
console.log(typeof undefined==typeof NULL);
console.log(typeof function () {}==typeof class {});
  1. 执行后a和b.age的值分别为
var a=10
var b={
    age: 11
}
function fn(x,y) {
    --y.age;
    return --x;
}
fn(a,b)
  1. 下面程序的执行结果是:
var number=4;
var numberFactorial=(function (number){
    return (number===0)? 1: number* factorial(number-1)
})(number)
console.log(numberFactorial)
  1. 下面程序的输出结果是:
var array=[]
for(var i=0; i < 3; i++) {
    array.push(()=> i)
}
var newArray=array.map(el=> el())
console.log(newArray)
  1. 下面程序的输出结果是:
function addToList(item, list) {
    return list.push(item)
}
const result=addToList("nowcoder", ["hello"])
console.log(result)

  1. 下面程序的输出结果是:
const first=()=> { console.log('first'); return false; }
const second=()=> { console.log('second'); return true; }
console.log( first() && second() );
console.log( second() || first() );
  1. 下面代码的输出结果是:
var s='12ab3cd', arr=s.split(/\d/);
console.log(arr[3],arr[4])
  1. 下面程序的输出结果是:
function getAge(...args) {
  console.log(typeof args);
}

getAge(21);
  1. 下面程序的输出结果是:
var arr=[1,2,3];
arr.push(arr.shift())
console.log(arr[1],arr[2])

JS深入

this指向

题目解析:this指向题目解析及扩展[3]

关于this还可以看看:可能是最好的 this 解析了...

  1. 下列程序的输出结果是多少?为什么?
var x=1;

var obj={
    x: 3,
    fun:function () {
        var x=5;
        return this.x;
    }
};

var fun=obj.fun;
console.log( obj.fun(), fun() );

  1. 下列程序的输出结果是多少?你能理清楚test函数的this指向吗?
var a=5;
 function test() { 
    a=0; 
    alert(a); 
    alert(this.a); 
    var a;
    alert(a); 
}
new test();

  1. 下列程序的输出结果是多少?为什么?
function fun () {
    return ()=> {
        return ()=> {
            return ()=> {
                console.log(this.name)
            }
        }
    }
}
var f=fun.call({name: 'foo'})
var t1=f.call({name: 'bar'})()()
var t2=f().call({name: 'baz'})()
var t3=f()().call({name: 'qux'})

  1. 执行以下代码,输出结果分别是多少?
let obj1={
    a: 1,
    foo: ()=> {
        console.log(this.a)
    }
}
// log1
obj1.foo()
const obj2=obj1.foo
// log2
obj2()
  1. 下面程序的输出结果是什么?为什么?
const Person=(name="wang",age=10)=> {
this.name=name;
this.age=age;
return this.name +' is '+ this.age + 'years old'
}
let result=new Person('zhang',11)
console.log(result)
  1. 请表述以下代码的执行结果和原因
var person={
  age: 18,
  getAge: function() {
    return this.age;
  }
};
var getAge=person.getAge
getAge()
  1. 请按顺序写出打印结果,并说明原因。
var name='global';
var obj={
    name: 'local',
    foo: function(){
        this.name='foo';
    }.bind(window)
};
var bar=new obj.foo();
setTimeout(function() {
    console.log(window.name);
}, 0);
console.log(bar.name);
 
var bar3=bar2=bar;
bar2.name='foo2';
console.log(bar3.name);

  1. 下面程序的执行结果是:
var obj={
    name:"zhangsan",
    sayName:function(){
        console.info(this.name);
    }
}

var wfunc=obj.sayName;
obj.sayName();
wfunc();
var name="lisi";
obj.sayName();
wfunc();
  1. 下面程序的输出结果是:
var name='test' 
var a={    
    name: 'ass',    
    getName: function() {    
        return this.name;   
    } 
} 
var b=a.getName; 
b();

事件循环

  1. 下列程序的输出结果分别是多少?为什么?
const promiseA=Promise.resolve('a')
promiseA. then((res)=> {
    console.log(res)
}).then((res)=> {
    console.log(res)
})
const promiseB=Promise.resolve('b')
promiseB. then((res)=> {
    console.log(res)
})
promiseB. then((res)=> {
    console.log(res)
})

  1. 下面程序的输出结果依次是多少?
setTimeout(()=> {
    console.log(1)
}, 0)

const P=new Promise((resolve, reject)=> {
    console.log(2)
    setTimeout(()=> {
        resolve()
        console.log(3)
    }, 0)
})

P.then(()=> {
    console.log(4)
})
console.log(5)
  1. 下面程序的输出结果是
setTimeout(function(){
    console.log(1);
}, 0)
new Promise(function(resolve){
    console.log(2);
    resolve();
    console.log(3);
}).then(function(){
    console.log(4);
})
console.log(5);

  1. 下面程序的输出结果是?
(async ()=> {
    console.log(1);
    setTimeout(()=> {
        console.log(2);
}, 0);
await new Promise((resolve, reject)=> {
    console.log(3);
}).then(()=> {
    console.log(4);
});
    console.log(5);
})();

  1. 下面程序的输出结果是:
new Promise((resolve)=> {
    console.log('1')
    resolve()
    console.log('2')
}).then(()=> {
    console.log('3')
})
setTimeout(()=> {
    console.log('4')
})
console.log('5')
  1. 下面程序的输出结果是:
var p1=new Promise(function(resolve, reject){
    resolve("2")
})
setTimeout(function(){
    console.log("1")
},10)
p1.then(function(value){
    console.log(value)
})
setTimeout(function(){
    console.log("3")
},0)

  1. 下面程序的输出结果是:
setTimeout(function() {
  console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});
  1. 请表述以下代码的执行结果和原因
setTimeout(function() {
    console.log(1)
},0)
new Promise(function executor(resolve){
    console.log(2)
    for (var i=0; i<10000; i++) {
        i - 9999 && resolve()
    }
    console.log(3)
}).then(function() {
    console.log(4)
})
console.log(5)
  1. 在网页中有两个div块,html代码如下
<div class="outer">
 <div class="inner"></div>
</div>

对应的js代码如下:

var outer=document.querySelector('.outer');
var inner=document.querySelector('.inner');

function onClick() {
    console.log('click');

    setTimeout(function() {
        console.log('timeout');
    }, 0);

    Promise.resolve().then(function() {
        console.log('promise');
    });

    outer.setAttribute('data-random', Math.random());
}

inner.addEventListener('click', onClick);
outer.addEventListener('click', onClick);

当点击class为inner的div块时,控制台依次输出结果是什么?10. 下面程序的输出结果是?

(async ()=> {
    console.log(1);
    setTimeout(()=> {
        console.log(2);
}, 0);
await new Promise((resolve, reject)=> {
    console.log(3);
}).then(()=> {
    console.log(4);
});
    console.log(5);
})();
  1. 下面程序的输出结果是:
setTimeout(()=> console.log('a'));
Promise.resolve().then(
   ()=> console.log('b’);
 ).then(
   ()=> Promise.resolve('c').then(
     (data)=> {
       setTimeout(()=> console.log('d'));
       console.log('f');
       return data;
     }
   )
 ).then(data=> console.log(data));

  1. 下面程序的输出结果是:
console.log('one'); 
setTimeout(function() { console.log('two'); }, 0); 
Promise.resolve()
       .then(function() { console.log('three'); })
 console.log('four');

  1. 下面程序的执行结果是:
setTimeout(function () {
    console.log(C)
},0)
console.log('D')
new Promise(function(resolve){
    console.log('E')
    resolve()
    console.log('F')
}).then(function() {
    console.log('G')
})
console.log('H')
  1. 有一个输出函数定义如下:
function log(msg, time) {
  return new Promise((resolve)=> {
    setTimeout(()=> {
      console.log(msg);
      resolve();
    }, time);
  });
}

则下面三段代码输出的结果是:

// 第一段代码:
(async ()=> {
  for (let i=0; i < 5; i++) {
    await log(i, 1000);
  }
})();
// 第二段代码:
(async ()=> {
  [ 1, 2, 3, 4 ].forEach(async (i)=> {
    await log(i, 1000);
  });
})();
// 第三段代码:
(async ()=> {
  for (const i of [ 1, 2, 3, 4 ]) {
    await log(i, 1000);
  }
})();

原型与原型链

关于原型JS:看完这篇文章,彻底了解 “原型” & “this”

传送门: 原型与原型链题目解析[4]

  1. 下面程序的输出结果依次是?
function Fn1(name) {
    if(name){
    this.name=name;
    }
}
Fn1.prototype.name="jack"
let a=new Fn1();
console.log('a:', a.name);

function Fn2(name) {
    this.name=name;
}
Fn2.prototype.name="jack"
let b=new Fn2();
console.log('b:', b.name);
  1. 下面程序的输出结果是?
var Foo=(function() {
    var x=0;
    function Foo() {}
    Foo.prototype.increment=function() {
        ++x;
        console.log(x);
    };
    return Foo;
})();
 
var a=new Foo();
a.increment();
a.increment();
var b=new Foo();
a.increment();
  1. 下面程序的输出结果是?
var name='Jay'
function Person(name){
    this.name=name;
    console.log(this.name)
}
var a=Person('Tom')
console.log(name)
console.log(a)
var b=new Person('Michael')
console.log(b)
  1. 请表述以下代码的执行结果和原因
class A{}
class B extends A{}
const a=new A()
const b=new B()
a.__proto__
b.__proto__
B. __proto__
B. prototype.__proto__
b.__proto__.__proto__
  1. 请表述以下代码的执行结果和原因
function test() {           
    getName=function() { 
        Promise.resolve().then(()=> console.log(0)); 
        console.log(1);               
    };

    return this; 
}
test.getName=function() { 
     setTimeout(()=> console.log(2), 0); 
     console.log(3);               
};
test.prototype.getName=function() {    

     console.log(4); 
};       
var getName=function() { 
     console.log(5);             
};
function getName() {

     console.log(6); 
}      
      
test.getName(); 
getName(); 
test().getName(); 
getName();  
new test.getName();
new test().getName();
new new test().getName();

  1. 请表述以下代码的执行结果和原因
var tmp={};
var A=function() {};
A. prototype=tmp;

var a=new A();
A. prototype={};

var b=Object.create(tmp);
b.constructor=A. constructor;

console.log(a instanceof A);
console.log(b instanceof A);

  1. 下面程序的执行结果是:
function Foo(){}
Foo.prototype.z=3;
var obj=new Foo();
console.info(obj.z)
obj.z=10;
console.info(obj.z);
delete obj.z;
console.info(obj.z);
  1. 下面程序的执行结果是:
const Book={
  price: 32
}
const book=Object.create(Book);
book.type='Math';
delete book.price;
delete book.type;
console.log(book.price);
console.log(book.type);

作用域与预编译

  1. 下面的程序会报错吗?如果不会,输出结果分别是多少?
function sayHello() {
    console.log(name);
    console.log(age);
    var name="Tom";
    let age=18;
} 
sayHello();
  1. 下面的程序i的打印结果分别是多少?
for (var i=0; i < 3; i++) {
    setTimeout(_=> {
        console.log(i)
    })
}

for (let i=0; i < 3; i++) {
    setTimeout(_=> {
        console.log(i)
    })
}
  1. 下面程序的输出结果是:
console.log(a);
var a='a';
console.log(b);
let b='b';
  1. 下面程序的输出结果是:
var foo="Hello";
(function(){
    var bar=" World";
    alert(foo + bar);
})();
alert(foo + bar);
  1. 下面程序的输出结果是:
var a=10;
(function () {
    console.log(a)
    a=5
    console.log(window.a)
    var a=20;
    console.log(a)
})()
  1. 下面代码的输出结果是:
const a=10
function runFunction() {
    const a=20
    console.log('inside', a)
}
runFunction()
console.log('outside', a)
  1. 请描述打印结果并说明原因
"use strict"
var name='Jay'
var person={
    name: 'Wang',
    pro: {
        name: 'Michael',
        getName: function () {
            return this.name
        }
    }
}
console.log(person.pro.getName)
var people=person.pro.getName
console.log(people())
  1. 下面程序的结果是:
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
<script>
var elements=document.getElementsByTagName("li");
for (var i=0;i<elements.length;i++){
    elements[i].onclick=function( ){
    alert(i); 
    };
}
  1. 下面程序的输出结果是
compute(10,100);
var compute=function(A,B) {
    console.info(A * B) ;
};
function compute(A,B){
    console.info(A + B);
}
function compute(A,B){
    console.info((A + B)*2);
}
compute(2,10);

  1. 下面程序的执行结果是:
meili()
function meili() {
    console.log("meili")
}
mogu()
var mogu=function() {
    console.log("mogu")
}
  1. 下面两个代码片段输出结果有什么区别?为什么?
// 片段1
check('first');
function check(ars){
    console.log(ars);
}
// 片段2
check('second');
var check=function(ars){
    console.log(ars);
}

ES6

对象

  1. 下面代码的输出结果是?
const student={name: 'ZhangSan'}
Object.defineProperty(student, 'age', {value: 22})
console.log(student)
console.log(Object.keys(student))

generator

  1. 下列程序的输出结果是多少?为什么?
function * cb(x, y) {
    for(let i=Math.ceil(x); i <=y; i++) {
        yield i;
    }
}

var a=cb(6, 9);
console.log(a.next());
console.log(a.next());

扩展运算符

  1. 下面程序的输出结果是:
function fn(...args) {
  console.log(typeof args);
}
fn(21);

promise

Promise.reject(0)
       .catch(e=> e)
       .catch(e=> console.log(e))

class

  1. 请写出下面ES6代码编译后所生成的ES5代码
class Person {
     constructor (name) {
          this.name=name;
     }
     greet () {
          console.log(`Hi, my name is ${this.name}`);
     }
     greetDelay (time) {
          setTimeout(()=> {
               console.log(`Hi, my name is ${this.name}`);
          }, time);
     }
}

标签模板

  1. 下面程序的输出结果是多少?
function getPersonInfo (one, two, three) {
    console.log(one)
    console.log(two)
    console.log(three)
}
const person='Lydia'
const age=21
getPersonInfo `${person} is ${age} years old`

module

  1. 请写出index里面的输出结果
// module.js
export default ()=> "Hello world"
export const name="nowcoder"
// index.js
import * as data from "./module"
console.log(data)

  1. 有a.js和b.js两个文件,请写出b文件中代码的输出
// a.js
let a=1
let b={}
setTimeout(()=> {    
a=2    
b.b=2
}, 100)
module.exports={ a, b }

// b.js
const a=require('./a')
console.log(a.a)
console.log(a.b)
setTimeout(()=> {    
    console.log(a.a)    
    console.log(a.b)
}, 500)

其他

  1. 输出结果是:
<div id="box1">
    <div id="box2">
        content
    </div>
</div>
<script>
const $=document.querySelector.bind(document);
const box1=$('#box1');
const box2=$('#box2');

box1.addEventListener('click', ()=>{
    console.log('box1 true');
}, true);

box1.addEventListener('click', ()=>{
    console.log('box1 false');
}, false);

box2.addEventListener('click', ()=>{
    console.log('box2 true');
}, true);

box2.addEventListener('click', ()=>{
    console.log('box2 false');
}, false);
</script>
  1. 输出结果是:
$(function () { 
    function fn1( value ) {
        alert( value );
    }
    function fn2( value ) {
        fn1("A");
        return false;
    }
    var callbacks=$.Callbacks();
    callbacks.add( fn1 ); 
    callbacks.fire( "B" );
    callbacks.add( fn2 ); 
    callbacks.fire( "C" );
})
  1. 实现在p元素后添加“Hello World!”,则横线处应使用的方法为( )?

<html>
    <head>
        <script type="text/javascript" src="/jquery/jquery.js"></script>
        <script type="text/javascript">
            $(document).ready(function(){
                $("button").click(function(){
                    $("<b>Hello World!</b>").______("p");
                });
            });
        </script>
    </head>
    <body>
        <p>This is a paragraph.</p>
        <p>This is another paragraph.</p>
        <button>在每个p元素的结尾添加内容</button>
    </body>
</html>
  1. 输出结果是:
<div id="box1">
  <div id="box2">
    content
  </div>
</div>
<script>
const $=document.querySelector.bind(document);
const box1=$('#box1');
const box2=$('#box2');
box1.addEventListener('click', ()=> {
  console.log('box1 true');
}, true);
box1.addEventListener('click', ()=> {
  console.log('box1 false');
}, false);
box2.addEventListener('click', ()=> {
  console.log('box2 true');
}, true);
box2.addEventListener('click', ()=> {
  console.log('box2 false');
}, false);
</script>
  1. 请选择下面代码输出1的次数

小夕:https://juejin.im/post/5cab0c45f265da2513734390

1. 基本类型有哪几种?null 是对象吗?基本数据类型和复杂数据类型存储有什么区别?

  • 基本类型有6种,分别是undefined,null,bool,string,number,symbol(ES6新增)。
  • 虽然 typeof null 返回的值是 object,但是null不是对象,而是基本数据类型的一种。
  • 基本数据类型存储在栈内存,存储的是值。
  • 复杂数据类型的值存储在堆内存,地址(指向堆中的值)存储在栈内存。当我们把对象赋值给另外一个变量的时候,复制的是地址,指向同一块内存空间,当其中一个对象改变时,另一个对象也会变化。

2. typeof 是否正确判断类型? instanceof呢? instanceof 的实现原理是什么?

首先 typeof 能够正确的判断基本数据类型,但是除了 null, typeof null输出的是对象。

但是对象来说,typeof 不能正确的判断其类型, typeof 一个函数可以输出 'function',而除此之外,输出的全是 object,这种情况下,我们无法准确的知道对象的类型。

instanceof可以准确的判断复杂数据类型,但是不能正确判断基本数据类型。

instanceof 是通过原型链判断的,A instanceof B, 在A的原型链中层层查找,是否有原型等于B.prototype,如果一直找到A的原型链的顶端(null;即Object.__proto__.__proto__),仍然不等于B.prototype,那么返回false,否则返回true.

instanceof的实现代码:

// L instanceof R
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O=R.prototype;// 取 R 的显式原型
 L=L.__proto__; // 取 L 的隐式原型
 while (true) { 
 if (L===null) //已经找到顶层
 return false; 
 if (O===L) //当 O 严格等于 L 时,返回 true
 return true; 
 L=L.__proto__; //继续向上一层原型链查找
 } 
}

3. for of , for in 和 forEach,map 的区别。

  • for...of循环:具有 iterator 接口,就可以用for...of循环遍历它的成员(属性值)。for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象、Generator 对象,以及字符串。for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。对于普通的对象,for...of结构不能直接使用,会报错,必须部署了 Iterator 接口后才能使用。可以中断循环。
  • for...in循环:遍历对象自身的和继承的可枚举的属性, 不能直接获取属性值。可以中断循环。
  • forEach: 只能遍历数组,不能中断,没有返回值(或认为返回值是undefined)。
  • map: 只能遍历数组,不能中断,返回值是修改后的数组。

PS: Object.keys():返回给定对象所有可枚举属性的字符串数组。

关于forEach是否会改变原数组的问题,有些小伙伴提出了异议,为此我写了代码测试了下(注意数组项是复杂数据类型的情况)。 除了forEach之外,map等API,也有同样的问题。

let arry=[1, 2, 3, 4];
arry.forEach((item)=> {
 item *=10;
});
console.log(arry); //[1, 2, 3, 4]
arry.forEach((item)=> {
 arry[1]=10; //直接操作数组
});
console.log(arry); //[ 1, 10, 3, 4 ]
let arry2=[
 { name: "Yve" },
 { age: 20 }
];
arry2.forEach((item)=> {
 item.name=10;
});
console.log(arry2);//[ { name: 10 }, { age: 20, name: 10 } ]

如还不了解 iterator 接口或 for...of, 请先阅读ES6文档: Iterator 和 for...of 循环

更多细节请戳: github.com/YvetteLau/B…


4. 如何判断一个变量是不是数组?

  • 使用 Array.isArray 判断,如果返回 true, 说明是数组
  • 使用 instanceof Array 判断,如果返回true, 说明是数组
  • 使用 Object.prototype.toString.call 判断,如果值是 [object Array], 说明是数组
  • 通过 constructor 来判断,如果是数组,那么 arr.constructor===Array. (不准确,因为我们可以指定 obj.constructor=Array)
function fn() {
 console.log(Array.isArray(arguments)); //false; 因为arguments是类数组,但不是数组
 console.log(Array.isArray([1,2,3,4])); //true
 console.log(arguments instanceof Array); //fasle
 console.log([1,2,3,4] instanceof Array); //true
 console.log(Object.prototype.toString.call(arguments)); //[object Arguments]
 console.log(Object.prototype.toString.call([1,2,3,4])); //[object Array]
 console.log(arguments.constructor===Array); //false
 arguments.constructor=Array;
 console.log(arguments.constructor===Array); //true
 console.log(Array.isArray(arguments)); //false
}
fn(1,2,3,4);

5. 类数组和数组的区别是什么?

类数组:

1)拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理);

2)不具有数组所具有的方法;

类数组是一个普通对象,而真实的数组是Array类型。

常见的类数组有: 函数的参数 arguments, DOM 对象列表(比如通过 document.querySelectorAll 得到的列表), jQuery 对象 (比如 $("div")).

类数组可以转换为数组:

//第一种方法
Array.prototype.slice.call(arrayLike, start);
//第二种方法
[...arrayLike];
//第三种方法:
Array.from(arrayLike);

PS: 任何定义了遍历器(Iterator)接口的对象,都可以用扩展运算符转为真正的数组。

Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象。


6.==和===有什么区别?

===不需要进行类型转换,只有类型相同并且值相等时,才返回 true.

==如果两者类型不同,首先需要进行类型转换。具体流程如下:

  1. 首先判断两者类型是否相同,如果相等,判断值是否相等.
  2. 如果类型不同,进行类型转换
  3. 判断比较的是否是 null 或者是 undefined, 如果是, 返回 true .
  4. 判断两者类型是否为 string 和 number, 如果是, 将字符串转换成 number
  5. 判断其中一方是否为 boolean, 如果是, 将 boolean 转为 number 再进行判断
  6. 判断其中一方是否为 object 且另一方为 string、number 或者 symbol , 如果是, 将 object 转为原始类型再进行判断
let person1={
 age: 25
}
let person2=person1;
person2.gae=20;
console.log(person1===person2); //true,注意复杂数据类型,比较的是引用地址

思考: []==![]

我们来分析一下: []==![] 是true还是false?

  1. 首先,我们需要知道 ! 优先级是高于==(更多运算符优先级可查看: 运算符优先级)
  2. ![] 引用类型转换成布尔值都是true,因此![]的是false
  3. 根据上面的比较步骤中的第五条,其中一方是 boolean,将 boolean 转为 number 再进行判断,false转换成 number,对应的值是 0.
  4. 根据上面比较步骤中的第六条,有一方是 number,那么将object也转换成Number,空数组转换成数字,对应的值是0.(空数组转换成数字,对应的值是0,如果数组中只有一个数字,那么转成number就是这个数字,其它情况,均为NaN)
  5. 0==0; 为true

7. ES6中的class和ES5的类有什么区别?

  1. ES6 class 内部所有定义的方法都是不可枚举的;
  2. ES6 class 必须使用 new 调用;
  3. ES6 class 不存在变量提升;
  4. ES6 class 默认即是严格模式;
  5. ES6 class 子类必须在父类的构造函数中调用super(),这样才有this对象;ES5中类继承的关系是相反的,先有子类的this,然后用父类的方法应用在this上。

8. 数组的哪些API会改变原数组?

修改 原数组的API有:

splice/reverse/fill/copyWithin/sort/push/pop/unshift/shift

不修改 原数组的API有:

slice/map/forEach/every/filter/reduce/entries/find

注: 数组的每一项是简单数据类型,且未直接操作数组的情况下(稍后会对此题重新作答)。


9. let、const 以及 var 的区别是什么?

  • let 和 const 定义的变量不会出现变量提升,而 var 定义的变量会提升。
  • let 和 const 是JS中的块级作用域
  • let 和 const 不允许重复声明(会抛出错误)
  • let 和 const 定义的变量在定义语句之前,如果使用会抛出错误(形成了暂时性死区),而 var 不会。
  • const 声明一个只读的常量。一旦声明,常量的值就不能改变(如果声明是一个对象,那么不能改变的是对象的引用地址)

10. 在JS中什么是变量提升?什么是暂时性死区?

变量提升就是变量在声明之前就可以使用,值为undefined。

在代码块内,使用 let/const 命令声明变量之前,该变量都是不可用的(会抛出错误)。这在语法上,称为“暂时性死区”。暂时性死区也意味着 typeof 不再是一个百分百安全的操作。

typeof x; // ReferenceError(暂时性死区,抛错)
let x;
复制代码
typeof y; // 值是undefined,不会报错

暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。


11. 如何正确的判断this? 箭头函数的this是什么?

this的绑定规则有四种:默认绑定,隐式绑定,显式绑定,new绑定.

  1. 函数是否在 new 中调用(new绑定),如果是,那么 this 绑定的是新创建的对象【前提是构造函数中没有返回对象或者是function,否则this指向返回的对象/function】。
  2. 函数是否通过 call,apply 调用,或者使用了 bind (即硬绑定),如果是,那么this绑定的就是指定的对象。
  3. 函数是否在某个上下文对象中调用(隐式绑定),如果是的话,this 绑定的是那个上下文对象。一般是 obj.foo()
  4. 如果以上都不是,那么使用默认绑定。如果在严格模式下,则绑定到 undefined,否则绑定到全局对象。
  5. 如果把 null 或者 undefined 作为 this 的绑定对象传入 call、apply 或者 bind, 这些值在调用时会被忽略,实际应用的是默认绑定规则。
  6. 箭头函数没有自己的 this, 它的this继承于上一层代码块的this。

测试下是否已经成功Get了此知识点(浏览器执行环境):

var number=5;
var obj={
 number: 3,
 fn1: (function () {
 var number;
 this.number *=2;
 number=number * 2;
 number=3;
 return function () {
 var num=this.number;
 this.number *=2;
 console.log(num);
 number *=3;
 console.log(number);
 }
 })()
}
var fn1=obj.fn1;
fn1.call(null);
obj.fn1();
console.log(window.number);


12. 词法作用域和this的区别。

  • 词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的
  • this 是在调用时被绑定的,this 指向什么,完全取决于函数的调用位置.

13. 谈谈你对JS执行上下文栈和作用域链的理解。

执行上下文就是当前 JavaScript 代码被解析和执行时所在环境, JS执行上下文栈可以认为是一个存储函数调用的栈结构,遵循先进后出的原则。

  • JavaScript执行在单线程上,所有的代码都是排队执行。
  • 一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
  • 每当进入一个函数的执行就会创建函数的执行上下文,并且把它压入执行栈的顶部。当前函数执行-完成后,当前函数的执行上下文出栈,并等待垃圾回收。
  • 浏览器的JS执行引擎总是访问栈顶的执行上下文。
  • 全局上下文只有唯一的一个,它在浏览器关闭时出栈。

作用域链: 无论是 LHS 还是 RHS 查询,都会在当前的作用域开始查找,如果没有找到,就会向上级作用域继续查找目标标识符,每次上升一个作用域,一直到全局作用域为止。


14. 什么是闭包?闭包的作用是什么?闭包有哪些使用场景?

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包最常用的方式就是在一个函数内部创建另一个函数。

闭包的作用有:

  1. 封装私有变量
  2. 模仿块级作用域(ES5中没有块级作用域)
  3. 实现JS的模块

15. call、apply有什么区别?call,aplly和bind的内部是如何实现的?

call 和 apply 的功能相同,区别在于传参的方式不一样:

  • fn.call(obj, arg1, arg2, ...),调用一个函数, 具有一个指定的this值和分别地提供的参数(参数的列表)。
  • fn.apply(obj, [argsArray]),调用一个函数,具有一个指定的this值,以及作为一个数组(或类数组对象)提供的参数。

call核心:

  • 将函数设为传入参数的属性
  • 指定this到函数并传入给定参数执行函数
  • 如果不传入参数或者参数为null,默认指向为 window / global
  • 删除参数上的函数
Function.prototype.call=function (context) {
 /** 如果第一个参数传入的是 null 或者是 undefined, 那么指向this指向 window/global */
 /** 如果第一个参数传入的不是null或者是undefined, 那么必须是一个对象 */
 if (!context) {
 //context为null或者是undefined
 context=typeof window==='undefined' ? global : window;
 }
 context.fn=this; //this指向的是当前的函数(Function的实例)
 let rest=[...arguments].slice(1);//获取除了this指向对象以外的参数, 空数组slice后返回的仍然是空数组
 let result=context.fn(...rest); //隐式绑定,当前函数的this指向了context.
 delete context.fn;
 return result;
}
//测试代码
var foo={
 name: 'Selina'
}
var name='Chirs';
function bar(job, age) {
 console.log(this.name);
 console.log(job, age);
}
bar.call(foo, 'programmer', 20);
// Selina programmer 20
bar.call(null, 'teacher', 25);
// 浏览器环境: Chirs teacher 25; node 环境: undefined teacher 25

apply:

apply的实现和call很类似,但是需要注意他们的参数是不一样的,apply的第二个参数是数组或类数组.

Function.prototype.apply=function (context, rest) {
 if (!context) {
 //context为null或者是undefined时,设置默认值
 context=typeof window==='undefined' ? global : window;
 }
 context.fn=this;
 let result;
 if(rest===undefined || rest===null) {
 //undefined 或者 是 null 不是 Iterator 对象,不能被 ...
 result=context.fn(rest);
 }else if(typeof rest==='object') {
 result=context.fn(...rest);
 }
 delete context.fn;
 return result;
}
var foo={
 name: 'Selina'
}
var name='Chirs';
function bar(job, age) {
 console.log(this.name);
 console.log(job, age);
}
bar.apply(foo, ['programmer', 20]);
// Selina programmer 20
bar.apply(null, ['teacher', 25]);
// 浏览器环境: Chirs programmer 20; node 环境: undefined teacher 25

bind

bind 和 call/apply 有一个很重要的区别,一个函数被 call/apply 的时候,会直接调用,但是 bind 会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。

Function.prototype.bind=function(context) {
 if(typeof this !=="function"){
 throw new TypeError("not a function");
 }
 let self=this;
 let args=[...arguments].slice(1);
 function Fn() {};
 Fn.prototype=this.prototype;
 let bound=function() {
 let res=[...args, ...arguments]; //bind传递的参数和函数调用时传递的参数拼接
 context=this instanceof Fn ? this : context || this;
 return self.apply(context, res);
 }
 //原型链
 bound.prototype=new Fn();
 return bound;
}
var name='Jack';
function person(age, job, gender){
 console.log(this.name , age, job, gender);
}
var Yve={name : 'Yvette'};
let result=person.bind(Yve, 22, 'enginner')('female');	


16. new的原理是什么?通过new的方式创建对象和通过字面量创建有什么区别?

new:

  1. 创建一个新对象。
  2. 这个新对象会被执行[[原型]]连接。
  3. 属性和方法被加入到 this 引用的对象中。并执行了构造函数中的方法.
  4. 如果函数没有返回其他对象,那么this指向这个新对象,否则this指向构造函数中返回的对象。
function new(func) {
 let target={};
 target.__proto__=func.prototype;
 let res=func.call(target);
 if (res && typeof(res)=="object" || typeof(res)=="function") {
 	return res;
 }
 return target;
}

字面量创建对象,不会调用 Object构造函数, 简洁且性能更好;

new Object() 方式创建对象本质上是方法调用,涉及到在proto链中遍历该方法,当找到该方法后,又会生产方法调用必须的 堆栈信息,方法调用结束后,还要释放该堆栈,性能不如字面量的方式。

通过对象字面量定义对象时,不会调用Object构造函数。


17. 谈谈你对原型的理解?

在 JavaScript 中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。使用原型对象的好处是所有对象实例共享它所包含的属性和方法。


18. 什么是原型链?【原型链解决的是什么问题?】

原型链解决的主要是继承问题。

每个对象拥有一个原型对象,通过 proto (读音: dunder proto) 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null(Object.proptotype.__proto__ 指向的是null)。这种关系被称为原型链 (prototype chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法。

构造函数 Parent、Parent.prototype 和 实例 p 的关系如下:(p.__proto__===Parent.prototype)

19. prototype 和 __proto__ 区别是什么?

prototype是构造函数的属性。

__proto__ 是每个实例都有的属性,可以访问 [[prototype]] 属性。

实例的__proto__ 与其构造函数的prototype指向的是同一个对象。

function Student(name) {
 this.name=name;
}
Student.prototype.setAge=function(){
 this.age=20;
}
let Jack=new Student('jack');
console.log(Jack.__proto__);
//console.log(Object.getPrototypeOf(Jack));;
console.log(Student.prototype);
console.log(Jack.__proto__===Student.prototype);//true

20. 使用ES5实现一个继承?

组合继承(最常用的继承方式)

function SuperType(name) {
 this.name=name;
 this.colors=['red', 'blue', 'green'];
}
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);
}

其它继承方式实现,可以参考《JavaScript高级程序设计》


21. 什么是深拷贝?深拷贝和浅拷贝有什么区别?

浅拷贝是指只复制第一层对象,但是当对象的属性是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。

深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

实现一个深拷贝:

function deepClone(obj) { //递归拷贝
 if(obj===null) return null; //null 的情况
 if(obj instanceof RegExp) return new RegExp(obj);
 if(obj instanceof Date) return new Date(obj);
 if(typeof obj !=='object') {
 //如果不是复杂数据类型,直接返回
 return obj;
 }
 /**
 * 如果obj是数组,那么 obj.constructor 是 [Function: Array]
 * 如果obj是对象,那么 obj.constructor 是 [Function: Object]
 */
 let t=new obj.constructor();
 for(let key in obj) {
 //如果 obj[key] 是复杂数据类型,递归
 t[key]=deepClone(obj[key]);
 }
 return t;
}


22. 防抖和节流的区别是什么?防抖和节流的实现。

防抖和节流的作用都是防止函数多次调用。区别在于,假设一个用户一直触发这个函数,且每次触发函数的间隔小于设置的时间,防抖的情况下只会调用一次,而节流的情况会每隔一定时间调用一次函数。

防抖(debounce): n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间

function debounce(func, wait, immediate=true) {
 let timer;
 // 延迟执行函数
 const later=(context, args)=> setTimeout(()=> {
 timer=null;// 倒计时结束
 if (!immediate) {
 func.apply(context, args);
 //执行回调
 context=args=null;
 }
 }, wait);
 let debounced=function (...params) {
 let context=this;
 let args=params;
 if (!timer) {
 timer=later(context, args);
 if (immediate) {
 //立即执行
 func.apply(context, args);
 }
 } else {
 clearTimeout(timer);
 //函数在每个等待时延的结束被调用
 timer=later(context, args);
 }
 }
 debounced.cancel=function () {
 clearTimeout(timer);
 timer=null;
 };
 return debounced;
};

防抖的应用场景:

  • 每次 resize/scroll 触发统计事件
  • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

节流(throttle): 高频事件在规定时间内只会执行一次,执行一次后,只有大于设定的执行周期后才会执行第二次。

//underscore.js
function throttle(func, wait, options) {
 var timeout, context, args, result;
 var previous=0;
 if (!options) options={};
 var later=function () {
 previous=options.leading===false ? 0 : Date.now() || new Date().getTime();
 timeout=null;
 result=func.apply(context, args);
 if (!timeout) context=args=null;
 };
 var throttled=function () {
 var now=Date.now() || new Date().getTime();
 if (!previous && options.leading===false) previous=now;
 var remaining=wait - (now - previous);
 context=this;
 args=arguments;
 if (remaining <=0 || remaining > wait) {
 if (timeout) {
 clearTimeout(timeout);
 timeout=null;
 }
 previous=now;
 result=func.apply(context, args);
 if (!timeout) context=args=null;
 } else if (!timeout && options.trailing !==false) {
 // 判断是否设置了定时器和 trailing
 timeout=setTimeout(later, remaining);
 }
 return result;
 };
 throttled.cancel=function () {
 clearTimeout(timeout);
 previous=0;
 timeout=context=args=null;
 };
 return throttled;
};

函数节流的应用场景有:

  • DOM 元素的拖拽功能实现(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove)
  • 搜索联想(keyup)
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

23. 取数组的最大值(ES5、ES6)

// ES5 的写法
Math.max.apply(null, [14, 3, 77, 30]);
// ES6 的写法
Math.max(...[14, 3, 77, 30]);
// reduce
[14,3,77,30].reduce((accumulator, currentValue)=>{
 return accumulator=accumulator > currentValue ? accumulator : currentValue
});

24. ES6新的特性有哪些?

  1. 新增了块级作用域(let,const)
  2. 提供了定义类的语法糖(class)
  3. 新增了一种基本数据类型(Symbol)
  4. 新增了变量的解构赋值
  5. 函数参数允许设置默认值,引入了rest参数,新增了箭头函数
  6. 数组新增了一些API,如 isArray / from / of 方法;数组实例新增了 entries(),keys() 和 values() 等方法
  7. 对象和数组新增了扩展运算符
  8. ES6 新增了模块化(import/export)
  9. ES6 新增了 Set 和 Map 数据结构
  10. ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例
  11. ES6 新增了生成器(Generator)和遍历器(Iterator)

25. setTimeout倒计时为什么会出现误差?

setTimeout() 只是将事件插入了“任务队列”,必须等当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码消耗时间很长,也有可能要等很久,所以并没办法保证回调函数一定会在 setTimeout() 指定的时间执行。所以, setTimeout() 的第二个参数表示的是最少时间,并非是确切时间。

HTML5标准规定了 setTimeout() 的第二个参数的最小值不得小于4毫秒,如果低于这个值,则默认是4毫秒。在此之前。老版本的浏览器都将最短时间设为10毫秒。另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常是间隔16毫秒执行。这时使用 requestAnimationFrame() 的效果要好于 setTimeout();


26. 为什么 0.1 + 0.2 !=0.3 ?

0.1 + 0.2 !=0.3 是因为在进制转换和进阶运算的过程中出现精度损失。

下面是详细解释:

JavaScript使用 Number 类型表示数字(整数和浮点数),使用64位表示一个数字。

图片说明:

  • 第0位:符号位,0表示正数,1表示负数(s)
  • 第1位到第11位:储存指数部分(e)
  • 第12位到第63位:储存小数部分(即有效数字)f

计算机无法直接对十进制的数字进行运算, 需要先对照 IEEE 754 规范转换成二进制,然后对阶运算。

1.进制转换

0.1和0.2转换成二进制后会无限循环

0.1 -> 0.0001100110011001...(无限循环)
0.2 -> 0.0011001100110011...(无限循环)

但是由于IEEE 754尾数位数限制,需要将后面多余的位截掉,这样在进制之间的转换中精度已经损失。

2.对阶运算

由于指数位数不相同,运算时需要对阶运算 这部分也可能产生精度损失。

按照上面两步运算(包括两步的精度损失),最后的结果是

0.0100110011001100110011001100110011001100110011001100

结果转换成十进制之后就是 0.30000000000000004。

27. promise 有几种状态, Promise 有什么优缺点 ?

promise有三种状态: fulfilled, rejected, pending.

Promise 的优点:

  1. 一旦状态改变,就不会再变,任何时候都可以得到这个结果
  2. 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数

Promise 的缺点:

  1. 无法取消 Promise
  2. 当处于pending状态时,无法得知目前进展到哪一个阶段

28. Promise构造函数是同步还是异步执行,then中的方法呢 ?promise如何实现then处理 ?

Promise的构造函数是同步执行的。then 中的方法是异步执行的。


29. Promise和setTimeout的区别 ?

Promise 是微任务,setTimeout 是宏任务,同一个事件循环中,promise.then总是先于 setTimeout 执行。


30. 如何实现 Promise.all ?

要实现 Promise.all,首先我们需要知道 Promise.all 的功能:

  1. 如果传入的参数是一个空的可迭代对象,那么此promise对象回调完成(resolve),只有此情况,是同步执行的,其它都是异步返回的。
  2. 如果传入的参数不包含任何 promise,则返回一个异步完成. promises 中所有的promise都“完成”时或参数中不包含 promise 时回调完成。
  3. 如果参数中有一个promise失败,那么Promise.all返回的promise对象失败
  4. 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组
Promise.all=function (promises) {
 return new Promise((resolve, reject)=> {
 let index=0;
 let result=[];
 if (promises.length===0) {
 resolve(result);
 } else {
 function processValue(i, data) {
 result[i]=data;
 if (++index===promises.length) {
 resolve(result);
 }
 }
 for (let i=0; i < promises.length; i++) {
 //promises[i] 可能是普通值
 Promise.resolve(promises[i]).then((data)=> {
 processValue(i, data);
 }, (err)=> {
 reject(err);
 return;
 });
 }
 }
 });
}


31.如何实现 Promise.finally ?

不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then.

Promise.prototype.finally=function (callback) {
 return this.then((value)=> {
 return Promise.resolve(callback()).then(()=> {
 return value;
 });
 }, (err)=> {
 return Promise.resolve(callback()).then(()=> {
 throw err;
 });
 });
}

32. 什么是函数柯里化?实现 sum(1)(2)(3) 返回结果是1,2,3之和。

函数柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

function sum(a) {
 return function(b) {
 return function(c) {
 return a+b+c;
 }
 }
}
console.log(sum(1)(2)(3)); // 6

引申:实现一个curry函数,将普通函数进行柯里化:

.Doctype作用?标准模式与兼容模式各有什么区别

<!DOCTYPE>声明位于位于HTML文档中的第一行,处于 <html>标签之前。告知浏览器的解析器,用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。
标准模式的排版 和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

2.HTML5 为什么只需要写 <!DOCTYPE HTML>?

HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照它们应该的方式来运行);
而HTML4.01基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。**

3.行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

首先:CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,如div的display默认值为“block”,则为“块级”元素;span默认display属性值为“inline”,是“行内”元素
(1)行内元素有:a b span img input select strong(强调的语气)
(2)块级元素有:div ul ol li dl dt dd h1 h2 h3 h4…p
(3)常见的空元素:


<img><input><link><meta>
鲜为人知的是:
<area><base><col><command><embed><keygen><param><source><track><wbr>
4.页面导入样式时,使用link和@import有什么区别?
link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS;
页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;

5.介绍一下你对浏览器内核的理解?

主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,然后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎则:解析和执行javascript来实现网页的动态效果。
最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。

6.常见的浏览器内核有哪些?

Trident内核:IE,MaxThon,TT,The World,360,搜狗浏览器等。[又称MSHTML]
Gecko内核:Netscape6及以上版本,FF,MozillaSuite/SeaMonkey等
Presto内核:Opera7及以上。 [Opera内核原为:Presto,现为:Blink;]
Webkit内核:Safari,Chrome等。 [ Chrome的:Blink(WebKit的分支)]

7.html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

  • HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。绘画 canvas;
    用于媒介回放的 video 和 audio 元素;
    本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
    sessionStorage 的数据在浏览器关闭后自动删除;
    语意化更好的内容元素,比如 article、footer、header、nav、section;
    表单控件,calendar、date、time、email、url、search;
    新的技术webworker, websocket, Geolocation;


移除的元素:
纯表现的元素:basefont,big,center,font, s,strike,tt,u;
对可用性产生负面影响的元素:frame,frameset,noframes;

  • 支持HTML5新标签:IE8/IE7/IE6支持通过document.createElement方法产生的标签,
    可以利用这一特性让这些浏览器支持HTML5新标签,
    浏览器支持新标签后,还需要添加标签默认的样式。
    当然也可以直接使用成熟的框架、比如html5shim;
    <!--[if lt IE 9]>
    <scriptsrc="http://html5shim.googlecode.com/svn/trunk/html5.js"> </script>
    <![endif]-->
  • 如何区分HTML5: DOCTYPE声明新增的结构元素功能元素
    H5新特性
    表单 画布 音视频 地理定位 媒体查询 css新特性 离线缓存 本地存储 拖拽

8.简述一下你对HTML语义化的理解?

用正确的标签做正确的事情。
html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO;
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。

9.HTML5的离线储存怎么使用,工作原理能不能解释一下?

在用户没有连网时,可以正常访问站点或应用,在用户与网络连接时更新用户机器上的缓存文件。
原理:HTML5的离线存储是基于一个新建的.appcache文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像cookie一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。
如何使用
页面头部像下面一样加入一个manifest的属性;
在cache.manifest文件的编写离线存储的资源;
CACHE MANIFEST
#v0.11
CACHE:
js/app.js
css/style.css
NETWORK:
resourse/logo.png
FALLBACK:
/ /offline.html
在离线状态时,操作window.applicationCache进行需求实现。

10.浏览器是怎么对HTML5的离线储存资源进行管理和加载的呢?

在线的情况下,浏览器发现html头部有manifest属性,它会请求manifest文件,如果是第一次访问app,那么浏览器就会根据manifest文件的内容下载相应的资源并且进行离线存储。如果已经访问过app并且资源已经离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的manifest文件与旧的manifest文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,那么就会重新下载文件中的资源并进行离线存储。
离线的情况下,浏览器就直接使用离线存储的资源。

11.iframe有那些缺点?

iframe会阻塞主页面的Onload事件;
搜索引擎的检索程序无法解读这种页面,不利于SEO;
iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。
使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript
动态给iframe添加src属性值,这样可以绕开以上两个问题。

12.Label的作用是什么?是怎么用的?

label标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

<label for="Name">Number:</label>
<input type=“text“name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>

13.如何实现浏览器内多个标签页之间的通信?

WebSocket、也可以调用localstorge、cookies等本地存储方式,还可以使用页面的路有参数传递
localstorge另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,
我们通过监听事件,控制它的值来进行页面信息通信;
14.如何在页面上实现一个圆形的可点击区域?
map+area或者svg
border-radius
纯js实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等

15.title与h1的区别、b与strong的区别、i与em的区别?

title属性没有明确意义只表示是个标题,H1则表示层次明确的标题,对页面信息的抓取也有很大的影响;
strong是标明重点内容,有语气加强的含义,使用阅读设备阅读网络时:会重读,而是展示强调内容。
i内容展示为斜体,em表示强调的文本;

16.data-属性的作用是什么?

h5新增的属性
可以通过ele.dataset获取到标签上的data-x的属性
返回一个对象

17.常见兼容性问题?

问题:png24位的图片在iE6浏览器上出现背景,

解决:解决方案是做成PNG8.

问题:浏览器默认的margin和padding不同。

解决:方案是加一个全局的*{margin:0;padding:0;}来统一。

问题:IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。浮动ie产生的双倍距离 #box{ float:left; width:10px; margin:0 0 0 100px;}这种情况之下IE会产生20px的距离**

解决:解决方案是在float的标签样式控制中加入 ——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“9”这一标记,将IE游览器从所有情况中分离出来。 接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css

.bb{ 
   background-color:#f1ee18;/*所有识别*/ 
  .background-color:#00deff\9; /*IE6、7、8识别*/ 
  +background-color:#a200ff;/*IE6、7识别*/ 
  _background-color:#1e0bd1;/*IE6识别*/ 
  } 

问题:IE下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性,Firefox下,只能使用getAttribute()获取自定义属性.

解决:解决方法:统一通过getAttribute()获取自定义属性.

问题:IE下,even对象有x,y属性,但是没有pageX,pageY属性,Firefox下,event对象有pageX,pageY属性,但是没有x,y属性.

解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。

问题:Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,

解决:可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决.

问题:超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了

解决:方法是改变CSS属性的排列顺序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}

18.你知道多少种Doctype文档类型?

该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。
HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。
XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。
Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。

19.HTML与XHTML——二者有什么区别?

1)所有的标记都必须要有一个相应的结束标记
2)所有标签的元素和属性的名字都必须使用小写
3)所有的XML标记都必须合理嵌套
4)所有的属性必须用引号""括起来
5)把所有<和&特殊符号用编码表示
6)给所有属性赋一个值
7)不要在注释内容中使“--”
8)图片必须有说明文字

20.<img>的title和alt有什么区别?

title是global attributes之一,用于为元素提供附加的advisory information。通常当鼠标滑动到元素上的时候显示。
alt是<img>的特有属性,是图片内容的等价描述,用于图片无法加载时显示、读屏器阅读图片。可提图片高可访问性,除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。

21.div+css的布局较table布局有什么优点?

改版的时候更方便 只要改css文件。
页面加载速度更快、结构化清晰、页面显示简洁。
表现与结构相分离。
易于优化(seo)搜索引擎更友好,排名更容易靠前。

22.CSS都有哪些选择器?

派生选择器(用HTML标签申明)
id选择器(用DOM的ID申明)
类选择器(用一个样式类名申明)
属性选择器(用DOM的属性申明,属于CSS2,IE6不支持,不常用,不知道就算了)
除了前3种基本选择器,还有一些扩展选择器,包括
后代选择器(利用空格间隔,比如div .a{ })
群组选择器(利用逗号间隔,比如p,div,#a{ })
那么问题来了,CSS选择器的优先级是怎么样定义的?

基本原则:

一般而言,选择器越特殊,它的优先级越高。也就是选择器指向的越准确,它的优先级就越高。
复杂的计算方法:
用1表示派生选择器的优先级
用10表示类选择器的优先级
用100标示ID选择器的优先级
div.test1 .span var 优先级 1+10 +10 +1
span#xxx .songs li 优先级1+100 + 10 + 1
xxx li 优先级 100 +1
那么问题来了,看下列代码,<p>标签内的文字是什么颜色的?
<style>
.classA{ color:blue;}
.classB{ color:red;}
</style>
<body>
<p class='classB classA'> 123 </p>
</body>
答案:red。与样式定义在文件中的先后顺序有关,即是后面的覆盖前面的,与在<p class=’classB classA’>中的先后关系无关。

23.行内元素和块级元素的具体区别是什么?行内元素的padding和margin可设置吗?

块级元素(block)特性:
总是独占一行,表现为另起一行开始,而且其后的元素也必须另起一行显示;
宽度(width)、高度(height)、内边距(padding)和外边距(margin)都可控制;
内联元素(inline)特性:
和相邻的内联元素在同一行;
宽度(width)、高度(height)、内边距的top/bottom(padding-top/padding-bottom)和外边距的top/bottom(margin-top/margin-bottom)都不可改变(也就是padding和margin的left和right是可以设置的),就是里面文字或图片的大小。
那么问题来了,浏览器还有默认的天生inline-block元素(拥有内在尺寸,可设置高宽,但不会自动换行),有哪些?
答案:<input> 、<img> 、<button> 、<texterea> 、<label>。

24.什么是外边距重叠?重叠的结果是什么?

外边距重叠就是margin-collapse。
在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。
折叠结果遵循下列计算规则:
两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
两个外边距一正一负时,折叠结果是两者的相加的和。

25.rgba()和opacity的透明效果有什么不同?

rgba()和opacity都能实现透明效果,但最大的不同是opacity作用于元素,以及元素内的所有内容的透明度,
而rgba()只作用于元素的颜色或其背景色。(设置rgba透明的元素的子元素不会继承透明效果!)

26.CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?

*   1.id选择器( # myid)
    2.类选择器(.myclassname)
    3.标签选择器(div, h1, p)
    4.相邻选择器(h1 + p)
    5.子选择器(ul < li)
    6.后代选择器(li a)
    7.通配符选择器( * )
    8.属性选择器(a[rel="external"])
    9.伪类选择器(a: hover, li: nth - child)
*   可继承: font-size font-family color, UL LI DL DD DT;
*   不可继承 :border padding margin width height ;
*   优先级就近原则,样式定义最近者为准;
*   载入样式以最后载入的定位为准;

优先级为:

   !important >  id > class > tag  
   important 比 内联优先级高

CSS3新增伪类举例:

p:first-of-type 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。
p:last-of-type  选择属于其父元素的最后 <p> 元素的每个 <p> 元素。
p:only-of-type  选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。
p:only-child    选择属于其父元素的唯一子元素的每个 <p> 元素。
p:nth-child(2)  选择属于其父元素的第二个子元素的每个 <p> 元素。
:enabled、:disabled 控制表单控件的禁用状态。
:checked,单选框或复选框被选中。

27.如何居中div,如何居中一个浮动元素?

给div设置一个宽度,然后添加margin:0 auto属性

div{

width:200px;
margin:0 auto;

}

居中一个浮动元素

  确定容器的宽高 宽500 高 300 的层
  设置层的外边距

.div {
Width:500px ; height:300px;//高度可以不设
Margin: -150px 0 0 -250px;
position:relative;相对定位
background-color:pink;//方便看效果
left:50%;
top:50%;
}

28.浏览器的内核分别是什么?经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用hack的技巧 ?

*  IE浏览器的内核Trident、 Mozilla的Gecko、google的WebKit、Opera内核Presto;
*  png24为的图片在iE6浏览器上出现背景,解决方案是做成PNG8.
*  浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
*  IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。 
  浮动ie产生的双倍距离 #box{ float:left; width:10px; margin:0 0 0 100px;} 
 这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 ——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
  渐进识别的方式,从总体中逐渐排除局部。 
  首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。 
  接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。

css

  .bb{
   background-color:#f1ee18;/*所有识别*/
  .background-color:#00deff\9; /*IE6、7、8识别*/
  +background-color:#a200ff;/*IE6、7识别*/
  _background-color:#1e0bd1;/*IE6识别*/
  }


*  IE下,可以使用获取常规属性的方法来获取自定义属性,
   也可以使用getAttribute()获取自定义属性;
   Firefox下,只能使用getAttribute()获取自定义属性. 
   解决方法:统一通过getAttribute()获取自定义属性.
*  IE下,even对象有x,y属性,但是没有pageX,pageY属性; 
  Firefox下,event对象有pageX,pageY属性,但是没有x,y属性.
* (条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。
*  Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示, 可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决.
超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
L-V-H-A :  a:link {} a:visited {} a:hover {} a:active {}

29.css优先级算法如何计算?

!important > id > class > 标签
!important 比 内联优先级高

  • 优先级就近原则,样式定义最近者为准;
  • 以最后载入的样式为准;

30.哪些css属性可以继承?

可继承: font-size font-family color, ul li dl dd dt;
不可继承 :border padding margin width height ;

DOM

讲 DOM 先从 HTML 讲起,讲 HTML 先从 XML 讲起。XML 是一种可扩展的标记语言,所谓可扩展就是它可以描述任何结构化的数据,它是一棵树!

1.documen.write和 innerHTML的区别

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

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

1)创建新节点

createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点

2)添加、移除、替换、插入

appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点

3)查找

getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性

3.attribute和property的区别是什么?

attribute是dom元素在文档中作为html标签拥有的属性;
property就是dom元素在js中作为对象拥有的属性。
所以:
对于html的标准属性来说,attribute和property是同步的,是会自动更新的,
但是对于自定义的属性来说,他们是不同步的,

4.src和href的区别

src用于替换当前元素,href用于在当前文档和引用资源之间确立联系。
src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。
Src source,指向外部资源的位置,如果我们添加<script src="js.js"></script>浏览器会暂停其他资源的下载和处理,直到该资源加载,编译,执行完毕(图片和框架也是如此),这也就是为什么js脚本要放在底部。
src用于替换当前元素,href用于在当前文档和引入资源之间建立联系。

存储

cookie

cookie 本身不是用来做服务器端存储的(计算机领域有很多这种“狗拿耗子”的例子,例如 CSS 中的 float),它是设计用来在服务器和客户端进行信息传递的,因此我们的每个 HTTP 请求都带着 cookie。但是 cookie 也具备浏览器端存储的能力(例如记住用户名和密码),因此就被开发者用上了。
使用起来也非常简单,document.cookie=....即可。
但是 cookie 有它致命的缺点:
存储量太小,只有 4KB
所有 HTTP 请求都带着,会影响获取资源的效率
API 简单,需要封装才能用

locationStorage 和 sessionStorage

后来,HTML5 标准就带来了sessionStorage和localStorage,先拿localStorage来说,它是专门为了浏览器端缓存而设计的。

其优点有:

存储量增大到 5MB
不会带到 HTTP 请求中
API 适用于数据存储 localStorage.setItem(key, value) localStorage.getItem(key)
sessionStorage的区别就在于它是根据 session 过去时间而实现,而localStorage会永久有效,应用场景不同。例如,一些需要及时失效的重要信息放在sessionStorage中,一些不重要但是不经常设置的信息,放在localStorage中。

对WEB标准以及W3C的理解与认识

标签闭合、标签小写、不乱嵌套、提高搜索机器人搜索几率、使用外 链css和js脚本、结构行为表现的分离、文件下载与页面速度更快、内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件,容易维 护、改版方便,不需要变动页面内容、提供打印版本而不需要复制内容、提高网站易用性;