前端面试题总汇一

技术题

1.new关键字的作用

  1. 创建一个空对象
  2. 将this指向这个对象
  3. 完成赋值
  4. 返回这个对象

2.什么是跨域,怎么解决

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
所谓同源是指,域名,协议,端口均相同,只要有任一不相同就会造成跨域

Jsonp
出于安全考虑,服务器不允许ajax跨域获取数据,但是可以跨域获取文件内容,所以基于这一点,可以动态创建script标签,使用标签的src属性访问js文件的形式获取js脚本,并且这个js脚本中的内容是函数调用,该函数调用的参数是服务器返回的数据,为了获取这里的参数数据,需要事先在页面中定义回调函数,在回调函数中处理服务器返回的数据,这就是解决跨域问题的主流解决方案

CORS(跨域资源共享)
CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。

3.前端开发的优化问题

(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) 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢。

4.什么是闭包(closure),为什么要用它?

简单的理解是函数的嵌套形成闭包,闭包包括函数本身已经它的外部作用域
使用闭包可以形成独立的空间,延长变量的生命周期,报存中间状态值

5.一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?

分为4个步骤:

  1. 当发送一个 URL 请求时,不管这个 URL 是 Web 页面的 URL 还是 Web 页面上每个资源的 URL,浏览器都会开启一个线程来处理这个请求,同时在远程 DNS 服务器上启动一个 DNS 查询。这能使浏览器获得请求对应的 IP 地址。
  2. 浏览器与远程 Web 服务器通过 TCP 三次握手协商来建立一个 TCP/IP 连接。该握手包括一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在 浏览器和服务器之间传递。该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由客户端发出该请求已经被接受的报文。
  3. 一旦 TCP/IP 连接建立,浏览器会通过该连接向远程服务器发送 HTTP 的 GET 请求。远程服务器找到资源并使用 HTTP 响应返回该资源,值为 200 的 HTTP 响应状态表示一个正确的响应。
  4. 此时,Web 服务器提供资源服务,客户端开始下载资源。

6.修改this指向的方法,它们有什么区别

一:call用法
window.color = 'red';
document.color = 'yellow';
var s1 = {color: 'blue'};
function changeColor () {
	console.log(this.color);
}
changeColor.call()	//不传参数默认指向window 输出:red
changeColor.call(window)	//指向window 输出:red
changeColor.call(document)	//指向document 输出:yellow
changeColor.call(this)	//构造函数的this如果打括号调用默认指向window 输出:red
changeColor.call(s1)	//指向s1对象 输出:blue
//例二:
var Pet = {
	words: '...',
	speak: function (say) {
		console.log(say + '' + this.words)
	}
}
Pet.speak('123')	//输出123...
var Dog = {
	words: 'WangWangWang'
}
Pet.speak.call(Dog,'123')	//输出123WangWangWang

二:apply用法:

window.number = 'one';
document.number = 'two';
var s1 = {number: 'three'};

function changeNum() {
	console.log(this.number)
}
changeNum.apply();	//one
changeNum.apply(window);	//one
changeNum.apply(document);//two
changeNum.apply(this);//one
changeNum.apply(s1);//three
//例二:
function Pet(words){
	this.words = words;
	this.speak = function(){
		console.log(this.words)
	}
}
function Dog(words){
	Pet.call(this,words);//结果wang
	// Pet.apply(this,arguments);//结果wang
}
var dog = new Dog('wang');
dog.speak();	//wang

apply和call的相同点:
都是为了用一个本不属于一个对象的方法,让这个对象去执行。

apply与call的区别:
接收的参数不同
apply()方法接收俩个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数和apply()方法的一样,但是传递给函数的参数必须一 一列举出来。
语法:
apply([thisObj [,argArray]]);
调用一个对象的一个方法,另一个对象替换当前对象
call([thisObj [,arg1[,arg2[…,argn]]]]);
说明:
如果thisObj是null或者undefined的时候,默认指向window。
如果argArray不是一个有效数组或不是arguments对象,那么将导致一个TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。
call方法可以用来代替另一个对象的一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,如果没有提供thisObj参数,那么Global对象被用于thisObj。

三:bind的用法:

var obj = {
	name: 'Tom'
}
function printName() {
	console.log(this.name)
}
var man = printName.bind(obj)
console.log(man)	//function(){...}
man()	//Tom
//例二:
function fn(a, b, c) {
	console.log(a, b, c);
}
var fn1 = fn.bind(null, 'Dot');
fn('A', 'B', 'C');	//A B C
fn1('A', 'B', 'C');           // Dot A B
fn1('B', 'C');                // Dot B C
fn.call(null, 'Dot');      // Dot undefined undefined
//例三:实现函数珂里化
var add = function(x) {
	return function(y) {
		return x + y;
	};
};
var increment = add(1);
var addTen = add(10);
increment(2)	//3
addTen(2)	//12

小总结:
Function.prototype.bind(thisArg) - - ES5

能够返回一个新函数,该新函数的主体与原函数主体一致,但当新函数被调用执行时,函数体中的this指向的是thisArg所表示的对象。

Function.prototype.call(this.Arg,val1,val2, …)

调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象

val1, val2, … 表示传递给调用函数的实际参数列表

Function.prototype.apply(thisArg, array|arguments)

调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象,

array|arguments 表示调用函数的参数列表,使用数组或类数组的格式

区别:
bind与call和apply的区别:
返回值的区别:
bind的返回值是一个函数,而call和apply是立即调用。
参数使用的区别:
bind与call一样是从第二个参数开始将想要传递的参数一 一写入。但call是把第二个及以后的参数作为fn方法的实参传进去,而fn1方法的实参实则是在bind中参数的基础上再往后排。

7.数组添加元素的方法

1.push()方法 : 将一个或多个元素添加到数组的末尾
参数 : 可以是一个, 可以是多个, 表示向数组里面添加元素 参数可以不填, 但是一般默认, 第一个参数必填
返回值 : 将指定的值添加到数组后的新数组长度
特点 : 直接改变原数组

var arr = [10, 20, 30]; 
var res = arr.push(50, 60);        
console.log(res);        
console.log(arr);

2.unshift() : 将一个或多个元素添加到数组的开头
参数 : 可以是一个, 可以是多个, 表示向数组里面添加元素 参数可以不填, 但是一般默认, 第一个参数必填
返回值 : 将指定的值添加到数组后的新数组长度
特点 : 直接改变原数组

arr.unshift(50, 60); 
console.log(arr);

3.splice() 修改, 添加, 删除一个数组中的某各项
参数 : 参数1 截取的起始下标
参数2 截取的元素个数
参数3到参数n : 表示替换或者添加的元素
返回值 : 截取的元素组成的新数组
特点 : 直接修改原数组
注意点 :
如果没有参数 返回值是空, 原数组不变
如果只有一个参数 这个参数表示截取的数组起始下标 它的用法和slice只有一个参数的效果是一样的, 返回值一样, 但是原数组发生了变化
如果只有两个参数 第一个参数是截取的数组起始下标 参数2 截取个数 这个是删除数组元素
如果有三个及以上参数 如果第二个参数值为0, 那么就表示添加新元素, 如果不为0, 表示删除对应个数的元素, 将新元素替换上去

console.log(arr.splice(1, 2)); // [20, 30]
console.log(arr);

8.h5操作自定义属性

使用attribute方法存取 data-* 自定义属性的值

<div id = "user" data-uid = "12345" data-uname = "hi" > </div>
// 使用getAttribute获取 data- 属性
var user = document . getElementById ( 'user' ) ;
var userName = plant . getAttribute ( 'data-uname' ) ; //hi
var userId = plant . getAttribute ( 'data-uid' ) ; //12345

// 使用setAttribute设置 data- 属性
user . setAttribute ( 'data-site' , 'lalala' ) ;

dataset属性存取data-*自定义属性的值

<div id="user" data-id="1234567890" data-name="cjt" data-date-of-birth> box </div>
<script type="text/javascript">
var el = document.querySelector('#user');
console.log(el.id); // 'user'
console.log(el.dataset);//一个DOMStringMap
console.log(el.dataset.id); // '1234567890'
console.log(el.dataset.name); // 'cjt'
console.log(el.dataset.dateOfBirth); // ''
el.dataset.dateOfBirth = '1985-01-05'; // 设置data-date-of-birth的值.
console.log('someDataAttr' in el.dataset);//false
el.dataset.someDataAttr = 'mydata';
console.log('someDataAttr' in el.dataset);//true

当我们添加自定义属性时 在自定义属性前 添加data-
取值的时候 去掉data- ,如果有多个单词,那么去掉data-和其他单词之间的- ,转成驼峰命名法

<div id="box" class="one" data-user-name="zs" data-height="160cm" data-weight="60kg" data-gender="男"></div>
var box = document.getElementById("box");

	console.log(box.dataset);

	console.log(box.dataset.height);
	console.log(box.dataset.userName);

9.前端的兼容性问题

  1. png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.

  2. 浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。

  3. IE8下,可以使用获取常规属性的方法来获取自定义属性,也可以使用getAttribute()获取自定义属性;Firefox下,只能使用getAttribute()获取自定义属性。解决方法:统一通过getAttribute()获取自定义属性。

  4. IE8下,even对象有x,y属性,但是没有pageX,pageY属性;Firefox下,event对象有pageX,pageY属性,但是没有x,y属性。

//解决方案:
var page = {};
page.x = event.x ? event.x : event.pageX;
page.y = event.y ? event.y:event.pageY;
  1. Chrome 中文界面下默认会将小于12px的文本强制按照12px显示,可通过加入CSS属性-webkit-text-size-adjust: none; 解决。

  2. 超链接访问过后hover样式就不出现了,被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}

  3. 块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大

    问题症状:常见症状是IE6中后面的一块被顶到下一行

    碰到频率:90%(稍微复杂点的页面都会碰到,float布局最常见的浏览器兼容问题)

    解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性

    备注:我们最常用的就是div+CSS布局了,而div就是一个典型的块属性标签,横向布局的时候我们通常都是用div float实现的,横向的间距设置如果用margin实现,这就是一个必然会碰到的兼容性问题。

  4. 设置较小高度标签(一般小于10px),在IE6,IE7,遨游中高度超出自己设置高度

    问题症状:IE6、7和遨游里这个标签的高度不受控制,超出自己设置的高度

    碰到频率:60%

    解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。

    备注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是IE8之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。

  5. 行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,IE6间距bug

    问题症状:IE6里的间距比超过设置的间距

    碰到几率:20%

    解决方案:在display:block;后面加入display:inline;display:table;

    备注:行内属性标签,为了设置宽高,我们需要设置display:block;(除了input/img标签比较特殊)。在用float布局并有横向的margin后,在IE6下,他就具有了块属性float后的横向margin的bug。不过因为它本身就是行内属性标签,所以我们再加上display:inline的话,它的高宽就不可设了。这时候我们还需要在display:inline后面加入display:talbe。

  6. 图片默认有间距

    问题症状:几个img标签放在一起的时候,有些浏览器会有默认的间距,通配符清除间距也不起作用。

    碰到几率:20%

    解决方案:使用float属性为img布局

    备注:因为img标签是行内属性标签,所以只要不超出容器宽度,img标签都会排在一行里,但是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道。(也可使用负margin,虽然能解决,但负margin本身就是容易引起浏览器兼容问题的用法,所以尽量不要使用)

  7. 浏览器兼容问题六:标签最低高度设置min-height不兼容

    问题症状:因为min-height本身就是一个不兼容的CSS属性,所以设置min-height时不能很好的被各个浏览器兼容

    碰到几率:5%

    解决方案:如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;}

    备注:在B/S系统前端开发时,有很多情况下我们有这种需求。当内容小于一个值(如300px)时。容器的高度为300px;当内容高度大于这个值时,容器高度被撑高,而不是出现滚动条。这时候我们就会面临这个兼容性问题。

  8. 浏览器兼容问题七:各种特殊样式的兼容,比如透明度、圆角、阴影等。特殊样式每个浏览器的代码区别很大,所以,只能现查资料通过给不同浏览器写不同的代码来解决。

  9. 清除浮动:

 .clearfix::after {
        content: "";
        display: table;
        clear: both;
    }
    
    .clearfix {
        *zoom: 1;
    }
  1. 盒模型
Element {
        box-sizing: border-box;
        /*box-sizing: content-box;*/
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值