1.如何判别Object、Array对象
通过Object.prototype.toString可以检测Object和Array(isArray对于检测Array很靠谱)
letobj={};
letarr=[];
console.log(Object.prototype.toString.call(obj));//[object Object]
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(null));//[object Null]
参考:你有必要知道的一些JavaScript 面试题(上)、在JavaScript中,如何判断数组是数组?
2.从这里可以知道self=this操作的意义(this的绑定):
var myObject = {
foo: "bar",
func: function() {
var self = this;
console.log( this.foo);//bar
console.log( self.foo);//bar
(function() {
console.log( this.foo);//undefined
console.log(self.foo);//bar
}());
}
};
myObject.func();
this还可以优雅的绑定:
varobj = {
func:function() {},
say:function() {
// 此时的this就是obj对象
setTimeout(function() {
console.log(this)
this.func()
}.bind(this));
}
}
obj.say();// obj
3.会输出什么?
console.log(1+"2"+"2");
console.log(1++"2"+"2");
console.log(1+-"1"+"2");
console.log(+"1"+"1"+"2");
console.log("A"-"B"+"2");
console.log("A"-"B"+2);
4.
var a={},
b={key:'b'},
c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);
reason:
The reason for this is as follows: When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since b and c are both objects, they will both be converted to “[object Object]”. As a result, a[b] anda[c] are both equivalent to a[“[object Object]”] and can be used interchangeably. Therefore, setting or referencing a[c] is precisely the same as setting or referencing a[b].
5.给你一个 DOM 元素,创建一个能访问该元素所有子元素的函数,并且要将每个子元素传递给指定的回调函数。
function Traverse(p_element,p_callback) {
p_callback(p_element);
var list = p_element.children;
for (var i = 0; i < list.length; i++) {
Traverse(list[i],p_callback); // recursive call
}
}
6.实现深度复制
// 判断arr是否为一个数组,返回一个bool值functionisArray(arr){returnObject.prototype.toString.call(arr) ==='[object Array]'; }// 深度克隆functiondeepClone(obj){if(typeofobj !=="object"&&typeofobj !=='function') {returnobj;//原始类型直接返回}varo = isArray(obj) ? [] : {};for(iinobj) {if(obj.hasOwnProperty(i)){ o[i] =typeofobj[i] ==="object"? deepClone(obj[i]) : obj[i]; } }returno;}
7.setTimeout 0
var fuc = [1,2,3];
for(var i in fuc){
setTimeout(function(){console.log(fuc[i])},0);
console.log(fuc[i]);
}
虽然setTimeout函数在每次循环的开始就调用了,但是却被放到循环结束才执行,循环结束,i=3,接连打印了3次3。
这里涉及到javascript单线程执行的问题:javascript在浏览器中是单线程执行的,必须在完成当前任务后才执行队列中的下一个任务。
另外,对于javascript还维护着一个setTimeout队列,未执行的setTimeout任务就按出现的顺序放到setTimeout队列,等待普通的任务队列中的任务执行完才开始按顺序执行积累在setTimeout中的任务。
所以在这个问题里,会先打印1 2 3,而将setTimeout任务放到setTimeout任务队列,等循环中的打印任务执行完了,才开始执行setTimeout队列中的函数,所以在最后会接着打印3次3。
由此,可以知道虽然设置为0秒后执行任务,实际上是大于0秒才执行的。可是这有什么用呢?
用处就在于我们可以改变任务的执行顺序!因为浏览器会在执行完当前任务队列中的任务,再执行setTimeout队列中积累的的任务。
通过设置任务在延迟到0s后执行,就能改变任务执行的先后顺序,延迟该任务发生,使之异步执行。
7.JSONP
8.JavaScript事件委托的技术原理
事件流:事件捕获阶段,处于目标阶段和事件冒泡阶段。
事件捕获是从外层元素到目标元素的过程,事件冒泡是从目标元素到外层元素的过程。如图:
事件委托的原理就是利用了事件冒泡,只需在DOM树中尽量最高的层次上添加一个事件处理程序,从而管理某一类型的所有事件。
添加到页面上的事件处理程序的数量直接影响到页面的整体性能,原因:
1)每个函数都是对象,都会占用内存,内存中对象越多,性能就越差
2)事先绑定所有的事件处理程序而导致的DOM访问次数,也会延迟整个页面的交互就绪时间
对“事件处理程序过多”问题的解决方案就是事件委托,因为只取得了一个DOM,只添加了一个事件处理程序,与普通方法相比,结果一样,但占用的内存更少。
9.浏览器加载、解析、渲染的过程
10.HTTP POST GET 本质区别详解
(1)GET提交,请求的数据会附在URL之后;POST提交:把提交的数据放置在是HTTP包的包体中。
(2)GET提交时,传输数据就会受到URL长度的 限制。POST:由于不是通过URL传值,理论上数据不受 限。
(3)POST的安全性要比GET的安全性高。
11.从输入URL到页面加载完成的过程中都发生了什么事情?
(1)输入地址
(2)浏览器查找域名的IP地址
这一步包括DNS具体的查找过程,包括:浏览器缓存->系统缓存->路由器缓存...
(3)浏览器向web服务器发送一个HTTP请求
(4)服务器的永久重定向响应(从http://example.com到http://www.example.com)
(5)浏览器跟踪重定向地址
(6)服务器处理请求
(7)服务器返回一个HTTP响应
(8)浏览器显示HTML
(9)浏览器发送请求获取嵌入在HTML中的资源(如图片、音频、视频、CSS、JS等等)
(10)浏览器发送异步请求
12.什么是语义化的html?
(1)有利于SEO,有利于搜索引擎爬虫更好的理解我们的网页,从而获取更多的有效信息,提升网页的权重。
(2)在没有CSS的时候能够清晰的看出网页的结构,增强可读性,能够便于开发者阅读和写出更优雅的代码。
13.href和src有什么区别?
href 表示超文本引用(hypertext reference),在 link和a 等元素上使用。src 表示来源地址,在 img、script、iframe 等元素上。
src和href之间存在区别,能混淆使用。src用于替换当前元素,href用于在当前文档和引用资源之间确立联系。
当浏览器解析到该元素时,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等元素也如此,类似于将所指向资源嵌入当前标签内。这也是为什么将js脚本放在底部而不是头部。
href是Hypertext Reference的缩写,指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,如果我们在文档中添加
那么浏览器会识别该文档为css文件,就会并行下载资源并且不会停止对当前文档的处理。这也是为什么建议使用link方式来加载css,而不是使用@import方式。
网友评论