【面试经历】问题总结
4.es6的几个新特性
糖语法 首先,语法糖是一种语法,使得语言更容易理解和更具有可读性,它使语言相对我们来说变得更"甜"。这也意味着ES6的一些"新"的特点并不是真的新,只是试图简化语法而已,让我们编程更容易。这样就无需使用老式的取巧的方法编写你的代码,而是可以一种更简单的方式来编写代码,那就是使用糖语法。 javascript并不像其他面向对象语言一样支持类这个概念,相反js使用function和prototype模拟类的概念。 下面是创建类的新语法,如果你有来自Java或其他OO语言的背景你会很熟悉: class Project { constructor(name) { this.name = name; } start() { return "Project " + this.name + " starting"; } } var project = new Project("Journal"); project.start(); // "Project Journal starting" 你在这个类中定义的所有方法都被加入这个类的原型prototype中。 既然JS不支持类,那么它支持继承吗? 是的,JS中继承是通过prototype实现。下面是WebProject子类继承Project类的代码: class WebProject extends Project { constructor(name, technologies) { super(name); this.technologies = technologies; } info() { return this.name + " uses " + arrayToString(this.technology); } } function arrayToString(param) { // ... some implementation } var webJournal = new WebProject("FrontEnd Journal", "javascript"); webJournal.start(); // "FrontEnd Journal starting" webJournal.info(); // "FrontEnd Journal uses javascript" 注意到在WebProject 构造器中,调用了Project的构造器,这样可以使用它的属性和方法。 模块Module 如果你想将所有js放在一个文件中,或者你要在应用的不同地方使用相同的功能,你就要使用模块,记住魔术的关键词是export,在你的函数之前使用export。 假设Project 和 WebProject 都储存在application.js文件中,如下源码结构: myproject (folder) | -- modules (folder) | | | -- helpers.js | -- application.js 如果我们从application.js中分离arrayToString(),然后放入modules/helpers.js,这样我们在其他地方可以重用它: // modules/helper.js export function arrayToString(param) { // some implementation } 这样我们只需要导入我们的模块即可: // application.js import { arrayToString } from 'modules/helpers'; class WebProject extends Project { constructor(name, technologies) { super(name); this.technologies = technology; } info() { return this.name + " uses " + arrayToString(this.technology); } } // ... let和const ES6中有两个新特性:let和 const,为了理解let,我们需要记住var是创建函数生存期内的变量: function printName() { if(true) { var name = "Rafael"; } console.log(name); // Rafael } 不像Java或其他语言,任何变量在JS中是在一个函数内创建,它会升级到哦函数之外部,不管你在哪里定义变量,都和你在函数顶部定义一样,这个行为称为hoisting。 上面代码用下面方式容易理解些: function printName() { var name; // variable declaration is hoisted to the top if(true) { name = "Rafael"; } console.log(name); // Rafael } 那么let是如何工作呢,和hoisting有什么关系,我们导入let的代码如下: function printName() { if(true) { let name = "Rafael"; } console.log(name); // ReferenceError: name is not defined } let是在一个代码块内,变量名只能在代码块中可见。 function printName() { var name = "Hey"; if(true) { let name = "Rafael"; console.log(name); // Rafael } console.log(name); // Hey } 总结:var是function-scoped,而let是 block-scoped. const是创建常量使用,一旦创建就一直不会被概念,如下: const SERVER_URL = "http://www.jdon.com" ES6还有其他新功能:Map, WeakMap, generators 和Proxies 那么什么时候可以使用ES6这些特性呢?可见下面这个网址: http://kangax.github.com/es5-compat-table/es6/ Node.JS的ES6特性可见:ES6 for Node 1. Function参数默认值 曾几何时,你编写了很多次如下代码: function beginTeleportation (who, options) { options = options || {} } 现在检查函数参数是否存在再也没有必要了, Default function parameters 默认函数参数能够让定义函数的默认参数。 function sayCosmicGreeting (greeting = 'Greetings', name = 'Earthling') { console.log(`${greeting}, ${name}`) } sayCosmicGreeting() // Greetings, Earthling sayCosmicGreeting('Salutations', 'Martian') // Salutations, Martian 这里函数参数greeting和name都有自己默认值,所以,如果你没有赋值空参数调用,就会输出默认值Greetings和 Earthling。 2.Rest参数 传递许多参数到函数中需要使用arguments 关键词: function sayCosmicGreetingTo (greeting) { const beings = arguments.slice(1) beings.forEach(being => { console.log(`${greeting}, ${being}`) }) } sayCosmicGreetingTo('Hello', 'Earthling', 'Martian', 'Neptunian') 上述代码问题会报错:TypeError: arguments.slice is not a function,因为arguments 不是实际数组,只是类似,为了能正常工作,你需要使用数组原型的call函数: Array.prototype.slice.call(arguments, 1) 但是这些处理手法对于初学者很费解,而Rest parameters解决这个问题,给你一个真正实际的Array数组实例: function sayCosmicGreetingTo (greeting, ...beings) { beings.forEach(being => { console.log(`${greeting}, ${being}`) }) } sayCosmicGreetingTo('Hello', 'Earthling', 'Martian', 'Neptunian') 注意到函数参数beings之前有“...”前缀,这个前缀表示这是一个数组,从0到数组最大长度之间的元素值是由实际传入参数决定的。 3.解构 在Javascript中普遍模式是将一个对象作为配置可选项,以前,这些选项得手工从对象中分解出来然后分配给相应变量。 function beginDepartureSequence (options) { const captain = options.captain const ship = options.ship const destination = options.destination console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 现在使用 destructure 可以直接将对象解构到变量,无论顺序: function beginDepartureSequence (options) { const { destination, captain, ship } = options console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 上面options对象被直接解构分配给了变量destination, captain, ship三个,我们可以做得更好,可以直接在函数参数中声明这些变量名: function beginDepartureSequence ({ destination, ship, captain }) { console.log(`Blast off sequence initiated for Captain ${captain} on ship ${ship} flying to ${destination}`) } beginDepartureSequence({ captain: 'Rey', ship: 'Millennium Falcon', destination: 'Jakku' }) 以上只是简单几个新特点,更多支持Javascript6 或Javascript7的特性可以参考:http://node.green/
5.mvc思想
模型(model)(数据层)-视图(view)(界面显示)-控制器(controller)(逻辑层)
mvc模式的核心思想是分离责任,使得数据、视图和逻辑部分分开,模型层关心的只是应用的状态以及业务逻辑而不用考虑数据如何展现给用户;视图层关心的是的只是如何根据模型的变化为用户提供用户界面;控制层则负责接收用户的输入然后将其交给对应的模型,它并不关心用户如何输入以及这些输入数据是如何作用于模型的。
7.解释一下前端数据与表现分离
什么是表现与数据分离 我一来就看了一篇文章,点进去一看结果说的是表现与结构分离,其大意是: 表现应该由CSS来控制,结构应该由html来控制,比如我们伟大的禅意花园。 于是我觉得,我简历是不是应该改成,表现与结构分离呢。。。。 但是我感觉表现与数据分离还是有点道理呢,所以我们还是回到我们的表现与数据分离吧。 ----------华丽的分割线---------- 半个小时过去了,我去查询了资料也去请教了前辈,最后得出了两个东西: MVC MVVM 很显然,他们说的这个也许是我找寻的答案,但是我心里面视乎并不买账,于是我找寻了以后截了一个图: 这是一个搞后端的大哥写的博客,我们看到采用MVC开发的主要目的就是表现与数据分离。 看来真的就是MVC啦。。。 好了,这个地方暂时打住,我们来看看当时的原话 模拟面试 面试官问我,说简历上写的对表现与数据分离有一定理解,可以描述一下么 我很淡定的说了句让我思考下,然后开始搜索着我的大脑硬盘,好像压根就没有这个词呢,于是胡乱蒙了个是不是html与css应该分离? 答案当然是否定的,然后面试哥把他在项目中遇到的一个问题抛了出来: 他有一个国家列表,现在要将国家列表放到A中,然后B可以由A选择,也可以有总列表选择 但是B中添加后,若是A中没有要动态为A增加这项。 为了方便各位理解,我上个图 不知道各位听到这个题作何感受,我当时其实就有一种方式可以实现(最简单,最土的),压根就没有想到这个题会和“表现与数据分离”有关系。 但是既然问到了,应该还是有联系吧,不知道各位怎么看待呢? 于是我们回到问题本身吧 再论行为与数据分离 我们工作中可能会碰到这种情况,美工每次拿过来的东西感觉都有点不一样,你不能说出有好大的不一样,反正就是有地方不一样。 然后一拿来后整个家伙全部完蛋,js报错啦,为什么报错你们懂的,这里我来现身说法,整一个真实的例子吧 当年我年少轻狂还在索贝时,我们有设计,但是设计同事的CSS很差,给我们的html+css经常有未闭合的标签,经常会出现莫名其妙的双引号。 但是当时我CSS也不好,其它同事完全就是搞后端的,所以在这个情况下我们艰难的做出了我们的第一版产品,与设计图一致(还是在设计的代码上修改的)。 完了领导看了提出了一点修改意见,于是设计同事又改了下图,相信我他只是简单的改了一点东西,然后形成了html交给了我们。。。。 这次拿来后我看到了这次的html结构和上次完全是两码事,而我们的产品又是单页应用,很多地方完全是JavaScript生成的,或者html标签与data形成了模板,现在要改。。。改毛线啊。。。 为了具体描述我们所遇到的困境我这里详细描述下: ① 我们根据设计第一版图做好了页面 ② 页面上有很多应用,是采用类似于js模板化的东西(小的封装的,很戳) ③ 页面根据数据库设计,前端使用js控制页面加载,最后渲染出我们的页面 好了整个代码还有点小复杂,完了现在设计哥来了一个完全不同的结构了,当时内部没有CSS高手,甚至说没有CSS熟手。 我负责改这个工作,我依稀记得我改出了翔。。。。最后终于改完了! 然后根据领导指示,设计同事给出了我们第三套HTML代码,这个和原来的差距相对大一点,但是主要模块还在,于是我看空中到处都是翔了。。。。 我不知道我前面的描述各位遇到过没有,但是当时我没能很好的解决这个问题,就只能缝缝补补的改着,每次出新东西后又是一场悲剧。 回到现实 其实我遇到的这个问题我感觉可以很好的说明表现数据分离的重要性了,但是什么是表现数据分离,我们还是需要将它说清楚啦。 PS:其实我遇到的问题比较复杂吧,我感觉都不完全是表现与数据分离了...... 我说不清楚什么是表现与数据分离,那我们举点反例吧: ① 服务器端(PHP/.net/Java),将html标签与数据一起打印出来 Response.Write("<div>......</div>"); 这段代码各位一定见过,可以想象,一个系统一年后要改版,这个地方的代码修改可能有点痛苦吧(特别是原来的开发人员不在了) 这个是服务器端的,那么我们的客户端呢(咳咳,让我想想啦,想不到啦。。。) ② 我想到一个例子,不知道合适不,拿出来说说吧 前段时间,我们前端有个地区控件的东西,他大概是这个样子的: var area = '<table>......</table>'; 他在字符串中将所有的地区全部写了出来(包括地区编号(隐藏)),这样做会有问题的: 假设我哪天想改变一下结构适应新的布局(响应式布局神马的随便啦),那么我们会发现无从下手 ③ 还是回到我遇到那个问题(重点来了哦) 我遇到那个问题其实主要是我在js中使用的id,或者class或者标签子选择器都不在了,新的代码上来后肯定出错啦。 这个问题很尖锐的,原来我使用了一套html+css页面,我们根据这个写了一大套javascript的东西,耗时3个月。 然后我们换了一套页面,但是其中功能还是我们那套js 然后我们再换了一套页面,其中的js还是我们那套js 最后最变态的要求出来了(因为产品会给不同的电视台使用),我们的产品在不同的人看起来页面是不一样的,但是其中的功能是一样的!!! 屌丝们,接招吧,各位哥哥,你们会怎么解决这个问题呢? 正是因为有上面那种莫名其妙的需求,所以才会出现我们前端MVC这种莫名其妙的东西。。。 因为按道理来说前端是不应该出现MVC的,我们的html就是model,我们的css就是view,我们的js就是controller。 结果现在单是javascript就搞出来了一套MVC,这不坑爹么? 至此,不知道各位对表现与数据分离有新的了解没有??? MVC——表现与数据分离 话不多说,先上一段代码(原来的代码,抄过来的): 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <script src="../jquery-1.7.1.js" type="text/javascript"></script> 5 <script type="text/javascript"> 6 $(document).ready(function () { 7 var end = $('#end'); 8 $('#pili').change(function () { 9 var name = ''; 10 var p = $(this).val(); 11 if (p == '叶小钗') { 12 name = '刀狂剑痴'; 13 } 14 if (p == '一页书') { 15 name == '百世经纶'; 16 } 17 if (p == '素还真') { 18 name = '清香白莲'; 19 } 20 21 end.html(name + p); 22 }); 23 }); 24 </script> 25 </head> 26 <body> 27 <select id="pili"> 28 <option value="叶小钗">叶小钗</option> 29 <option value="一页书">一页书</option> 30 <option value="素还真">素还真</option> 31 </select> 32 <div id="end"></div> 33 </body> 34 </html> 我们重新看看上面的代码,很简单的逻辑,select改变后变化end的值,好了现在需求发生改变: ① select变成使用input模拟select ② 在手机上还是使用select算了 ③ 总会有莫名其妙的需求,这个就是 好吧,现在的代码你该怎么写呢?是不是会写几个代码,或者你压根不知道怎么写呢???于是看看我们的MVC的实现吧 PS:代码是我可耻的抄的。。。。但我可是自豪的一个字一个字的敲的哦,窃知识不算偷...... 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <title></title> 4 <script src="../jquery-1.7.1.js" type="text/javascript"></script> 5 <script type="text/javascript"> 6 $(document).ready(function () { 7 //定义一个controller 8 var piliController = { 9 //选择视图 10 start: function () { 11 this.view.start(); 12 }, 13 //将用户操作映射到模型更新上 14 set: function (name) { 15 this.model.setPerson(name); 16 } 17 }; 18 piliController.model = { 19 piliKV: { 20 '叶小钗': '刀狂剑痴', 21 '一页书': '百世经纶', 22 '素还真': '清香白莲' 23 }, 24 curPerson: null, 25 //数据模型负责业务逻辑和数据存储 26 setPerson: function (name) { 27 this.curPerson = this.piliKV[name] ? name : null; 28 this.onchange(); 29 }, 30 //通知数据同步更新 31 onchange: function () { 32 piliController.view.update(); 33 }, 34 //相应视图对当前状态的查询 35 getPiliAction: function () { 36 return this.curPerson ? this.piliKV[this.curPerson] + this.curPerson : '???'; 37 } 38 }; 39 piliController.view = { 40 //用户触发change事件 41 start: function () { 42 $('#pili').change(this.onchange); 43 }, 44 onchange: function () { 45 piliController.set($('#pili').val()); 46 }, 47 update: function () { 48 $('#end').html(piliController.model.getPiliAction()); 49 } 50 }; 51 piliController.start(); 52 }); 53 </script> 54 </head> 55 <body> 56 <select id="pili"> 57 <option value="叶小钗">叶小钗</option> 58 <option value="一页书">一页书</option> 59 <option value="素还真">素还真</option> 60 </select> 61 <div id="end"></div> 62 </body> 63 </html> 我们来看看这个神一样的代码。。。。我们一开始会认为他有这些问题: ① 代码维护困难,至少我认为很困难 ② 徒增复杂性,性能会有问题 ③ 我并不能说服自己说自己懂了。。。。 于是我们就放弃了MVC啦,但是我们回过头来好好审视下他,我们会发现不一样的东西: ① 我们好像就在view中使用了选择器获取dom,其它地方压根不认识dom这个丫的。 ② 我们的数据似乎在model中,我们可以随意改变,但是并不会影响到我们dom ③ view和model是完全独立的,我们的controller恰好把他们串联起来了 看着这神奇的魔法,我似懂非懂的点了点头,你妹的MVC还真他妈够劲!!!
8.js事件的三个阶段:
js事件的三个阶段分别为:捕获、目标、冒泡
1.捕获:事件由页面元素接收,逐级向下,到具体的元素
2.目标:具体的元素本身
3.冒泡:跟捕获相反,具体元素本身,逐级向上,到页面元素
事件捕获:当使用事件捕获时,父级元素先触发,子元素后触发
事件冒泡:当使用事件冒泡时,子级元素先触发,父元素后触发
W3C : 任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达事件源,再从事件源向上进行事件捕获
*IE和W3C不同绑定事件解绑事件的方法有什么区别,参数分别是什么,以及事件对象e有什么区别
标准浏览器:addEventListener("click","doSomething","true")方法,若第三参数为true则采用事件捕获,若为false,则采用事件冒泡
IE浏览器只支持事件冒泡,不支持事件捕获,所以它不支持addEventListener("click","doSomething","true")方法,所以ie浏览器使用ele.attachEvent("onclick",doSomething)
事件对象e的区别:
在触发DOM上的某个事件时,会产生一个事件对象event
在ie中事件对象定义为window.event
事件传播的阻止方法:
再W3C中,使用stopPropagation()方法
在IE下使用cancelBubble = true方法
阻止默认行为:
再W3c中,使用preventDefault()方法
再IE下return false
9.【事件的代理/委托】的原理以及优缺点。
原理:
事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是让别人来做,这个事件本来是加在某些元素上的,然而你却加到别人身上来做,完成这个事件。
也就是:利用冒泡的原理,把事件加到父级上,触发执行效果
优点是
1、可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒
2、可以实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适
缺点:事件代理的应用常用应该仅限于上述需求下,如果把所有事件都用代理就可能会出现事件误判,即本不应用触发事件的被绑上了事件
10.前端性能优化。
网络性能优化,加快访问速度,浏览器并行加载数量,怎样实现原生JS异步载入,CDN加速的原理,如何将不同静态资源发布到多个域名服务器上,发布后这些静态字段的url路径改怎么批量改写,用什么工具进行项目打包,css打包后的相对路径怎么转换为绝对路径,用什么工具进行项目模块依赖管理,怎么进行cookie优化等等
11.闭包原理及其应用
什么情况下会发生闭包,为什么需要闭包,什么场景下需要,闭包闭了谁,怎么释放被闭包的变量内存,闭包的优点是什么,缺点是什么。参考网址1 参考网址2
12.跨域
JavaScript跨域总结与解决办法(http://www.cnblogs.com/rainman/archive/2011/02/20/1959325.html)
跨域-知识(http://www.cnblogs.com/scottckt/archive/2011/11/12/2246531.html)
跨域资源共享的10种方式(http://www.cnblogs.com/cat3/archive/2011/06/15/2081559.html)
13.jsonp原理
可以把需要跨域的请求改成用script脚本加载即可,服务器返回执行字符串,但是这个字符串是在window全局作用域下执行的,你需要把他返回到你的代码的作用域内,这里就需要临时创建一个全局的回调函数,并把到传到后台,最后再整合实际要请求的数组,返回给前端,让浏览器直接调用,用回调的形式回到你的原代码流程中。
将url的查询参数解析成字典对象
这个题目不约而同的出现在了多家公司的面试题中,当然也是因为太过于典型,解决方案无非就是拆字符或者用正则匹配来解决,我个人强烈建议用正则匹配,因为url允许用户随意输入,如果用拆字符的方式,有任何一处没有考虑到容错,就会导致整个js都报错。而正则就没有这个问题,他只匹配出正确的配对,非法的全部过滤掉,简单,方便。
实现代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function getQueryObject(url) {
url = url == null ? window.location.href : url;
var search = url.substring(url.lastIndexOf("?") + 1);
var obj = {};
var reg = /([^?&=]+)=([^?&=]*)/g;
search.replace(reg, function (rs, $1, $2) {
var name = decodeURIComponent($1);
var val = decodeURIComponent($2);
val = String(val);
obj[name] = val;
return rs;
});
return obj;
}
|
函数节流
对于常见的场景,如网页滚动时,经常会有滚动到哪时做什么样的动画效果,遂要注册onscroll事件,如何减少触发次数,到达优化性能,同时又满足效果要求不卡顿,一个是优化事件内代码,减少代码量,二就是做函数节流。
大部分节流都采用时间做节流,即时间间隔小于多少的不再调用,但同时保证一个最小调用间隔。(否则拖拽类的节流都将无效果),也可以用调用次数做节流,但要考虑最后一次调用需要要执行。
可以参考:浅谈javascript的函数节流(http://www.alloyteam.com/2012/11/javascript-throttle/)
设计模式
这方面被问到的比较多的有观察者模式,职责链模式,工厂模式
主要是应用于js开发组件中会经常涉及,纯粹的页面业务逻辑可能涉及不多。
比如如何去设计一个前端UI组件,应该公开出哪些方法,应该提供哪些接口,应该提供哪些事件。哪部分逻辑流程应该开放出去让用户自行编写,如何实现组件与组件之间的通信,如何实现高内聚低耦合,如何实现组件的高复用等等
css垂直居中方法
可以看到我提到上面大多数都是关于JS的面试题,主要是因为css并不是我的强项,但有几个出现频率很高,就是经典的垂直居中问题。
这个问题又可以细分为,被垂直居中的元素是否定高,是文字还是块,文字是单行还是多行文字等等
这个可以百度下,有N多种解决方案,主要还是看应用场景的限制。
自适应布局
这个问题可以划分为,左固定右自适应宽度,上固定下固定中间自适应高度等等布局要求。
关于左右自适应的,不低于10种解决方案,还要看dom结构要求是并列还是嵌套,是否允许有父级元素,是否允许使用CSS3,是否有背景色,是否要两列等高,等等
而关于自适应高度的解决方案就略少一些,大致也是靠,CSS3的calc属性,内padding,绝对定位后拉伸,动态js计算等等解决方案,同样也是要看应用场景能用哪个
移动端自适应
也被问到了很多移动端开发中的各种坑,比如2倍屏,3倍屏的自适应等
js中this的理解
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
AMD与CommonJS的区别与共同点
共同点:两者都是为了实现模块化编程而出现的,对于大型项目,参与人数多,代码逻辑复杂,是最适合使用模块化的思想来完成整个项目的。同时采用这种思想也很便于对整个项目进行管控。
区别:CommonJS是适用于服务器端的,著名的Node执行环境就是采用的CommonJS模式。它是同步加载不同模块文件。之所以采用同步,是因为模块文件都存放在服务器的各个硬盘上,实际的加载时间就是硬盘的文件读取时间。
AMD,Asynchronous Module Definition,即异步模块定义。它是适用于浏览器端的一种模块加载方式。从名字可知,AMD采用的是异步加载方式(js中最典型的异步例子就是ajax)。浏览器需要使用的js文件(第一次加载,忽略缓存)都存放在服务器端,从服务器端加载文件到浏览器是受网速等各种环境因素的影响的,如果采用同步加载方式,一旦js文件加载受阻,后续在排队等待执行的js语句将执行出错,会导致页面的‘假死’,用户无法使用一些交互。所以在浏览器端是无法使用CommonJS的模式的。目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js
CMD (通用模块定义) seajs 懒执行,就近依赖
javascript null,undefined,undeclared的区别
1.undefined表示"缺少值",就是此处应该有一个值,但是还没有定义,转为数值时为NaN。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
2.null表示"没有对象",即该处不应该有值,转为数值时为0。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
3.undeclared:js语法错误,没有申明直接使用,js无法找到对应的上下文。
我:
http://www.jackpu.com/2016ge-da-hu-lian-wang-gong-si-qian-duan-mian-shi-ti-hui-zong/
我:
https://www.zhihu.com/question/41466747?sort=created
我:
作者:汪汪
链接:https://www.zhihu.com/question/41466747/answer/132562725
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
(10)浏览器的垃圾回收机制
垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存,内存泄露和浏览器实现的垃圾回收机制息息相关, 而浏览器实现标识无用变量的策略主要有下两个方法:
第一,引用计数法
跟踪记录每个值被引用的次数。当声明一个变量并将引用类型的值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次 数加1.相反,如果包含对这个值引用的变量又取得另外一个值,则这个值的引用次数减1.当这个值的引用次数变成0时,则说明没有办法访问这个值了,因此就 可以将其占用的内存空间回收回来。
如: var a = {}; //对象{}的引用计数为1
b = a; //对象{}的引用计数为 1+1
a = null; //对象{}的引用计数为2-1
所以这时对象{}不会被回收;
IE 6, 7 对DOM对象进行引用计数回收, 这样简单的垃圾回收机制,非常容易出现循环引用问题导致内存不能被回收, 进行导致内存泄露等问题,一般不用引用计数法。
第二,标记清除法
到2008年为止,IE,Firefox,Opera,Chrome和Safari的javascript实现使用的都是标记清除式的垃圾收集策略(或类似的策略),只不过垃圾收集的时间间隔互有不同。
标记清除的算法分为两个阶段,标记(mark)和清除(sweep). 第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。
我:
https://www.zhihu.com/question/41466747?sort=created
我:
http://www.cnblogs.com/bigboyLin/p/5272902.html
我:
浏览器兼容问题?如何区分 HTML 和
HTML5?
HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
绘画 canvas
用于媒介回放的 video 和 audio 元素
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
sessionStorage 的数据在浏览器关闭后自动删除
语意化更好的内容元素,比如 article、footer、header、nav、section
表单控件,calendar、date、time、email、url、search
新的技术webworker, websockt, Geolocation
移除的元素
纯表现的元素:basefont,big,center,font, s,strike,tt,u;
对可用性产生负面影响的元素:frame,frameset,noframes;
支持HTML5新标签:
IE8/IE7/IE6支持通过document.createElement方法产生的标签,
可以利用这一特性让这些浏览器支持HTML5新标签,
浏览器支持新标签后,还需要添加标签默认的样式:
我:
内联元素居中方案
水平居中设置:
1.行内元素
设置 text-align:center;
2.Flex布局
设置display:flex;justify-content:center;(灵活运用,支持Chroime,Firefox,IE9+)
垂直居中设置:
1.父元素高度确定的单行文本(内联元素)
设置 height = line-height;
2.父元素高度确定的多行文本(内联元素)
a:插入 table (插入方法和水平居中一样),然后设置 vertical-align:middle;
b:先设置 display:table-cell 再设置 vertical-align:middle;
块级元素居中方案
水平居中设置:
1.定宽块状元素
设置 左右 margin 值为 auto;
2.不定宽块状元素
a:在元素外加入 table 标签(完整的,包括 table、tbody、tr、td),该元素写在 td 内,然后设置 margin 的值为 auto;
b:给该元素设置 displa:inine 方法;
c:父元素设置 position:relative 和 left:50%,子元素设置 position:relative 和 left:50%;
我:
(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布局慢。对普通的网站有一个统一的思路,就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言是无法“优化”的。
我:
3.http状态码有那些?分别代表是什么意思?
100-199 用于指定客户端应相应的某些动作。
200-299 用于表示请求成功。
300-399 用于已经移动的文件并且常被包含在定位头信息中指定新的地址信息。
400-499 用于指出客户端的错误。400 1、语义有误,当前请求无法被服务器理解。401 当前请求需要用户验证 403 服务器已经理解请求,但是拒绝执行它。
500-599 用于支持服务器错误。 503 – 服务不可用
4.一个页面从输入 URL 到页面加载显示完成,这个过程中都发生了什么?(流程说的越详细越好)
查找浏览器缓存
DNS解析、查找该域名对应的IP地址、重定向(301)、发出第二个GET请求
进行HTTP协议会话
客户端发送报头(请求报头)
文档开始下载
文档树建立,根据标记请求所需指定MIME类型的文件
文件显示
浏览器这边做的工作大致分为以下几步:
加载:根据请求的URL进行域名解析,向服务器发起请求,接收文件(HTML、JS、CSS、图象等)。
解析:对加载到的资源(HTML、JS、CSS等)进行语法解析,建议相应的内部数据结构(比如HTML的DOM树,JS的(对象)属性表,CSS的样式规则等等)
我:
作者:汪汪
链接:https://www.zhihu.com/question/41466747/answer/132562725
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
(10)浏览器的垃圾回收机制
垃圾收集器必须跟踪哪个变量有用哪个变量没用,对于不再有用的变量打上标记,以备将来收回其占用的内存,内存泄露和浏览器实现的垃圾回收机制息息相关, 而浏览器实现标识无用变量的策略主要有下两个方法:
第一,引用计数法
跟踪记录每个值被引用的次数。当声明一个变量并将引用类型的值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次 数加1.相反,如果包含对这个值引用的变量又取得另外一个值,则这个值的引用次数减1.当这个值的引用次数变成0时,则说明没有办法访问这个值了,因此就 可以将其占用的内存空间回收回来。
如: var a = {}; //对象{}的引用计数为1
b = a; //对象{}的引用计数为 1+1
a = null; //对象{}的引用计数为2-1
所以这时对象{}不会被回收;
IE 6, 7 对DOM对象进行引用计数回收, 这样简单的垃圾回收机制,非常容易出现循环引用问题导致内存不能被回收, 进行导致内存泄露等问题,一般不用引用计数法。
第二,标记清除法
到2008年为止,IE,Firefox,Opera,Chrome和Safari的javascript实现使用的都是标记清除式的垃圾收集策略(或类似的策略),只不过垃圾收集的时间间隔互有不同。
标记清除的算法分为两个阶段,标记(mark)和清除(sweep). 第一阶段从引用根节点开始标记所有被引用的对象,第二阶段遍历整个堆,把未标记的对象清除。