1、写出以下代码的执行结果: 1 : ________,2: ________
[1,2,3].toString()
({}).toString.call([1,2,3])
答案:'1,2,3'、[object Array]
解:
2、描述在浏览器中敲入一个网址并按下回车后所发生的事情(尽量详细)
解:首先进行域名解析:浏览器向本地服务器请求当前域名对应的IP地址,若成功则返回该IP地址;然后浏览器向该IP对应的网站发起请求,该网站返回请求的网页及相应的文件并渲染到浏览器中。若前边域名服务器解析域名出错,就返回给浏览器上级服务器的IP,浏览器再向此服务器发起域名解析请求。
3、请写出一下代码的执行结果
var test='hello,world';
(function(){
console.log(test);
var test='hello,test';
})();
var test='hello,world';
(function(){
console.log(test);
function test(){
console.log('hello,test');
}
})();
答案:
undefined
[Function: test]
解:此处考的是变量的提升与函数声明的提升。
4、描述 GET 和 POST 的区别
解:get从服务器上获取数据,post向服务器传送数据;
get是将数据添加到URL的末尾,有大小限制,post将数据放在协议体中,一般没有大小限制;
post较get安全。
5、请实现一个fibonacci函数,要求其参数和返回值如下所示:
/**
*@desc: fibonacci
*@param: count {Number}
*@return: result {Number} 第count个fibonacci值,计数从0开始
fibonacci数列为:[1, 1, 2, 3, 5, 8, 13, 21, 34 …]
则getNthFibonacci(0)返回值为1
则getNthFibonacci(4)返回值为5
*/
解:看需求选择方法。
方法一:非递归:
function getNthFibonacci(count) {
if (count<2) {
return 1;
}
var arr=[1,1];
for(var i=2;i<=count;i++){
arr[i]=arr[i-1]+arr[i-2];
}
return arr[count];
}
方法二:递归:
function getNthFibonacci(count) {
if (count<2) {
return 1;
}
return getNthFibonacci(count-1)+getNthFibonacci(count-2);
}
6、根据代码回答问题。
问:三行x,y ,z的输出分别是什么?
function fun(n,o){
console.log(o);
return {
fun:function(m){
return fun(m,n);
}
};
}
var x=fun(0);x.fun(1);
var y=fun(0).fun(1).fun(2);
var z=fun(0).fun(1);z.fun(2);z.fun(3);
答案:
undefined 0
undefined 0 1
undefined 0 1 1
解:
X的值:x=fun(0)调用fun函数,传入参数n=0,则打印o为undefined,返回值是一个对象;x.fun(1)调用了返回对象的fun方法,传入参数m=1,返回值是fun(1,0),返回之前又调用了fun函数,参数n=1,o=0,打印o为0,返回一个对象。故打印出undefined和0
Y的值:y=fun(0).fun(1)同上,至此打印出了undefined和0,返回值是对象,又.fun(2)调用返回对象的fun方法,传入参数m=3,返回fun(3,1),但返回之前又调用了fun函数,参数n=3,o=1,打印o为1,返回一个对象。故打印出undefined和0和1
Z的值:z=fun(0).fun(1);z.fun(2);同上Y,至此打印出了undefined和0和1,z.fun(3);又打印出了1。故结果undefined和0和1和1
7、填写内容让下面代码支持a.name='name1'; b.name='name2';
function obj(name){
_____
}
obj.____= "name2";
var a = obj("name1");
var b = new obj;
答案:
if (name) {this.name=name;}return this;
prototype.name
解:此题有个注意点:要判断name属性存在。
若不判断,直接this.name=name;return this;
这样的话在var b = new obj时没有传入name的值,即b有name属性,但值为undefined,即使原型上有name='name2'。若delete b.name便会沿着原型链向上找。
8、写一个求和的函数sum,达到下面的效果 【重点掌握!】
// Should equal 15
sum(1, 2, 3, 4, 5);
// Should equal 0
sum(5, null, -5);
// Should equal 10
sum('1.0', false, 1, true, 1, 'A', 1, 'B', 1, 'C', 1, 'D', 1,
'E', 1, 'F', 1, 'G', 1);
// Should equal 0.3, not 0.30000000000000004
sum(0.1, 0.2);
答案:
function sum(...arr) {
return arr.map(function(item){
return isNaN(parseFloat(item))?0:Number(item);
}).reduce(function(a,b){
let r1=0,r2=0,width=0,max=0;
try{ //获取a的小数部分长度
r1=a.toString().split(".")[1].length;
}catch(e){
r1=0;
}
try{ //获取b的小数部分长度
r2=b.toString().split(".")[1].length;
}catch(e){
r2=0;
}
max=Math.max(r1,r2); //获取两数的最大小数长度
width=Math.pow(10,max); //获取数字化的最大宽度
return (a+b).toFixed(max)*width/width;//返回两数的和四舍五入为指定小数位数的数字
}); //reduce函数将返回值赋给当前值
}
解:toFixed()方法可把Number四舍五入为指定小数位数的数字。
语法:NumberObject.toFixed(num)
掌握:数组的map()方法、reduce()方法。
①map方法:
语法:array.map(function(currentValue,index,arr), thisValue)
currentValue必需。当前元素
index可选。当前元素的索引
arr 可选。当前元素所属的数组对象。
注意:
map()方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
map()方法按照原始数组元素顺序依次处理元素。
map() 不会对空数组进行检测。
map() 不会改变原始数组。
②reduce方法:
语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
total必需。初始值, 或者计算结束后的返回值。
currentValue必需。当前元素
currentIndex可选。当前元素的索引
arr 可选。当前元素所属的数组对象。
initialValue可选。传递给函数的初始值
注意:
reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce()对于空数组是不会执行回调函数的。
9、用JavaScript写一个图片跑马灯程序,要求图片从右向左动态无缝移动。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
*{padding: 0; margin: 0;}
#slide{
width: 900px;
height: 160px;
position: relative;
margin: 30px auto;
border: 1px solid #ccc;
}
#slide:hover{
cursor: pointer;
}
#slide .list{
width: 840px;
height: 160px;
overflow: hidden;
margin: 0 auto;
position: relative;
}
#slide .list-item{
list-style: none;
float: left;
width: 140px;
height: 160px;
background: #c1c1c1;
overflow: hidden;
opacity: 0.5;
}
.current{
border:2px solid red;
list-style: none;
height: 160px;
width: 50%;
position: absolute;
left: 25%;
background: red;
z-index: 9999;
}
#slide .next,#slide .prev{
position: absolute;
width: 30px;
height: 28px;
background: #999;
overflow: hidden;
text-decoration: none;
}
#slide .next{right: 0; top: 66px;}
#slide .prev{left: 0; top: 66px;}
</style>
</head>
<body>
<div id="slide">
<ul class="list" id="list">
<li class="current">1</li>
<li class="list-item">2</li>
<li class="list-item">3</li>
<li class="list-item">4</li>
<li class="list-item">5</li>
<li class="list-item">6</li>
<li class="list-item">7</li>
<li class="list-item">8</li>
<li class="list-item">9</li>
<li class="list-item">10</li>
</ul>
<a class="next" id="next" href="javascript:;">next</a>
<a class="prev" id="prev" href="javascript:;">prev</a>
</div>
<script type="text/javascript">
window.onload=function(){
class Slider{
constructor(id){
this.container=document.getElementById(id);//获取图片容器
this.items=this.container.querySelectorAll('li');
}
getSelectorItem(){ //获取当前展示的图片
let selected=this.container.querySelector('.current');
return selected;
}
getSelectorItemIndex(){ //获取当前选中的图片的索引
return Array.from(this.items).indexOf(this.getSelectorItem());
}
slideTo(idx){ //跳转到idx这一张图片
let selected=this.getSelectorItem();
if(selected){
selected.className="list-item";//将当前展示的图片设置'隐藏样式'
}
let item=this.items[idx];
if(item){
item.className="current";//将要展示的图片设置'显示样式'
}
}
slideNext(){ //下一张
let currentIdx=this.getSelectorItemIndex();
//防止最后一张,使其循环显示
let nextIdx=(currentIdx+1)%this.items.length;
this.slideTo(nextIdx);
}
slidePrev(){ //上一张
let currentIdx=this.getSelectorItemIndex();
//防止第一张,使其循环显示
let prevIdx=(this.items.length+currentIdx-1)%this.items.length;
this.slideTo(prevIdx);
}
}
//创建实例,绑定作用域,自动循环
let slider=new Slider('list');
let timer=setInterval(slider.slideNext.bind(slider),1000);
let sli=document.getElementById('slide');
let prev=document.getElementById('prev');
let next=document.getElementById('next');
sli.onmouseover=function(){ //清除定时器
clearInterval(timer);
};
sli.onmouseout=function(){ //重设定时器
timer=setInterval(slider.slideNext.bind(slider),1000);
};
sli.onmousewheel=function(e){
//判断滚动方向
parseInt(e.wheelDelta)>0?slider.slideNext():slider.slidePrev();
}
next.onclick=function(){ //下一张
if (slider.getSelectorItemIndex()!==slider.items.length-1) {
slider.slideNext();
}else{
next.style.cursor='default'; //图片滚动到末尾时不可点击
}
};
prev.onclick=function(){ //前一张
if (slider.getSelectorItemIndex()!==0) {
slider.slidePrev();
}else{
prev.style.cursor='default'; //图片滚动到第一张时不可点击
}
};
}
</script>
</body>
</html>
10、下面哪些语句可以在JS里判断一个对象oStringObject是否为String。
oStringObject instanceof String
typeof oStringObject == 'string'
oStringObject is String
以上答案都不正确
答案:A
解:此题有套路!题目说oStringObject是对象,那么typeof的结果一定是对象;
instanceof用来判断是不是对象的实例;所以A正确。
11、JS原型、原型链有什么特点?
解:
1. 原型对象也是普通的对象,是对象一个自带隐式的 __proto__属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null 的话,我们就称之为原型链
2. 原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链
12、JavaScript脚本如何对一个对象进行深度Clone?【掌握】
答案:
若支持JSON格式,则:
function deepClone(obj){
var str=JSON.stringify(obj);
var newObj=JSON.parse(str);
return newObj;
}
若不支持JSON格式,则:
function deepClone(obj){
if(!obj){
return null;
}
var newObj=obj instanceof Array?[]:{};//判断是数组还是对象
for(var attr in obj){
if(obj.hasOwnProperty(attr)){//判断该属性是不是在对象obj自身
newObj[attr]=typeof obj[attr]==='object'?deepClone(obj[attr]):obj[attr];
//判断当前属性值是不是对象,如果是则递归
}
}
return newObj;
}
13、下面关于块内声明函数的做法哪些是正确的?
if (x) { function foo() {}}
if (x) { var foo = function() {}}
if (x) { foo = function() {}}
ECMAScript明确的规范了块内函数,javascript实现了这个规范
答案:B
解:一般我们尽量不要在if语句内声明函数,当必须要声明时用函数表达式,不用函数声明是为了防止函数声明提升导致if条件没有用。
14、 Event对象的target和currentTarget有什么区别?
target是触发事件的元素;currentTarget是绑定事件的元素。
15、javascript里面的继承怎么实现,如何避免原型链上面的对象共享。【重要】
解:
JS中的继承通过原型链实现,基本思想是利用原型让一个引用类型继承另一个引用类型的方法和属性。
存在的问题:①原型链上面的对象共享原型属性及方法。②创建子类型的实例时,不能向超类型的构造函数中传递参数。
注意:通过原型链实现继承时,不能使用对象字面量创建原型方法。否则会重写原型连。
解决共享的方法:利用借用构造函数技术,即在子类型构造函数的内部调用超类型构造函数。用apply()和call()绑定作用域。同时还可以向超类型中传递参数。
16、一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?
解:①在远程DNS服务器上查询请求对应的IP地址;
②建立TCP/IP连接,与远程Web服务器;
③进行Http请求,返回正确响应;
④下载资源,渲染到页面。
17、实现点击表头排序功能,点一次降序,再点一次升序
解:获取表中元素内容添加进数组中进行排序或反转,在将数组的内容替换到表中。
18、angularjs1中定义服务哪种方法是错误的?
$provide
factory
service
$instance
答案:D
定义服务的方式有如下几种:
使用系统内置的$provide服务
使用Module的factory方法
使用Module的service方法
19、如何判断一个js对象是否是Array,arr为要判断的对象,其中最准确的方法是?
typeof(arr)
arr instanceof Array
arr.toString==='[object Array]';
Object.prototype.toString.call(arr) === '[object Array]';
答案:最准确选D,B其实也可以,不过好像会在IFrame中会失效。
还有一种方法就是Array.isArray(arr)
20、如下代码输出的结果是什么:
console.log(1+ "2"+"2");
console.log(1+ +"2"+"2");
console.log("A"- "B"+"2");
console.log("A"- "B"+2);
答案:
122
32
NaN2
NaN
解:
console.log(1+ "2"+"2");数字和字符串相加得到字符串。
console.log(1+ +"2"+"2");第一个+"2"中加号是一元操作符,试图进行NUmber()运算,得到数字2.
console.log("A"- "B"+"2");NUmber("A")得到NaN,加法操作中,若有一个是NaN,则结果为NaN,然后进行字符串合并。
console.log("A"- "B"+2);同上,只不过最后和数字相加,得到NaN。
21、某饭店要开发一个排队软件。非VIP用户需要排队,先到先得。VIP用户可以插队,但是VIP用户之间需要按到达时间先后排队。
要求实现:①addCustomer(String phoneNumber)函数②有空位时获取排到的用户③用户进店排队时的函数current()
代码:
class Customer{
constructor(flag,time,number){
this.vip=flag;
this.time=time;
this.phoneNumber=number;
}
getVip(){
return this.vip;
}
getTime(){
return this.time;
}
getNumber(){
return this.phoneNumber;
}
}
class Queue{
constructor(){
this.Q=[];
this.vipQ=[];
this.notVipQ=[];
}
add(c){
if (c.vip) { //c是Customer的实例
this.vipQ.push(c.phoneNumber);
}else{
this.notVipQ.push(c.phoneNumber);
}
}
getCustomer(){
if (!this.Q.length&&this.notVipQ.length) {
if (!this.vipQ.length) {
this.Q.push(this.notVipQ.shift());
}else{
this.Q.push(this.vipQ.shift());
}
}
}
}
22、关于angularjs1说法,错误的是
前端mvc,极大降低前端开发的耦合
极大的丰富了dom操作
实现了数据双向绑定
实现了依赖注入
答案:B
解:angular减少了对DOM的访问;jQuery极大地丰富了DOM访问。
23、JS数组去重【ES6实现】
代码:
Array.prototype.delRep=function(){
var set=new Set(this);
return [...set];
}
24、如何获取UA?
解:使用navigator对象
1.appCodeName,浏览器代码名的字符表示
2.appName,浏览器的名称
3.appVersion 返回brower平台和版本信息
4.platform,返回运行浏览器的操作系统平台
5.userAgent,返回客户机发送给服务器的useragent头部的值
代码:
function whatBrowser(){
document.Browser.Name.value=navigator.appName;
document.Browser.Verson.value=navigator.appVersion;
document.Browser.Code.value=navigator.appCodeName;
document.Browser.Agent.value=navigator.userAgent;
}
25、性能优化的方法?
解:
1. 减少http请求次数:CSS Sprites, JS、CSS 源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存,图片服务器
2. 前端模板JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
3. 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
4. 当需要设置的样式很多时设置className而不是直接操作style
5. 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作
6. 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)
7. 图片预加载,将样式表放在顶部,将脚本放在底部,加上时间戳
26、请你谈谈Cookie的弊端
解:大小限制:每个cookie位4k左右,每个特定的域名下最多20个;
不安全:容易被拦截,造成信息泄露;
额外开销:cookie在每次发起Http请求时都会被发送到服务器,造成带宽浪费和额外开销。
27、如何实现浏览器内多个标签页之间的通信?
解:用cookie或localStorage,页面之间信息是共享的;而sessionStorage不共享。
28、.call() 和 .apply() 的作用?
解:改变上下文,修改this指向;
语法:Function.apply(obj,args)
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
.call()和.apply()一样,只是参数是参数列表不是数组。