23. 监听输入:javascript
1. oninput > onchange: onchange在离焦事件是触发。不如input灵敏 ( IE9+ )css
2. 中文输入时(即非直接输入),input获取的值不正确,需加判断。( IE9+ )html
compositionstart:当浏览器有非直接的文字输入时, compositionstart事件会以同步模式触发.vue
compositionEnd: 当浏览器是直接的文字输入时, compositionend会以同步模式触发.html5
var cpLock = false; input.addEventListener('compositionstart', function(){ cpLock = true; }) input.addEventListener('compositionend', function(){ cpLock = false; }) input.addEventListener('input', function(){ if(!cpLock)console.log(this.value); });
3. 须要兼容IE9一下的,只能使用keyPress,keyDown等事件,判断keyCodejava
(参考作法:http://jyren-rachel.iteye.com/blog/1886275)react
24. 递归中的性能:es6
递归是处遍历外最经常使用的循环方法。鉴于其性能问题,通常能用while,for等循环的尽可能不用递归。 若必须用递归方法,通常把递归中的执行代码放入setTimeout方法中,以免栈溢出(setTimeout老是在下一次的tick中执行)。web
setInterval的不靠谱:当每次执行的时间小于循环时间时,不会出现异常;而当代码执行时间较长,超出循环时间时,下一次的循环将被延后,这样每次的循环间隔将不统一,且任务会堆积在队列中。gulp
更详细的介绍https://www.cnblogs.com/simonbaker/p/5707270.html
25. es6属性:
1. let , const
let : a. 不存在变量提高, 必须先声明 后使用。(会报错 is not defined ;var 中则不报错,返回值为 undefined)
b. 存在块做用域内,同域内不可重复声明
c. 暂时性死区:一旦在做用域内声明了次变量,若提早访问会报错,(即便外域也声明了同名变量)
const : 与 let 特色相同,声明时必须赋值,且不能更改赋值,如果对象保存的是对象的地址。
2. 结构赋值 : 等号右边的值会赋予左边的变量。
3. 模板字符串: ‘字符串’,按照字符串处理拼接。
a. 反引号为特殊字符,使用的话需加 \ 转义。
b. 花括号内能够进行 js 运算
c. 空格、缩进都会被保留
`${1}+${2}` // '1+2'
4. rest参数 , 扩展运算符
rest : (. . .a) 做为参数或者等号左边变量 必须为最后一个参数
扩展运算符: 至关于rest的逆运算, 展开一个数组或者对象
5.class 类,super方法:(阮一峰:https://m.imooc.com/article/20618)
注:react中通常写法: super ( props );这样写的缘由是 在constructor 中可使用 this.props, props是实例化时传入的参数。
(子类才会有super方法,父类是没有的);在子类的构造函数中,只有调用super以后,才能使用this关键字,不然会报错,这是由于子类没有本身的this对象,而是继承父类的this对象,而后对其进行加工,若是不调用super方法,子类就得不到this对象;
若是子类没有定义constructor方法,这个方法会默认添加,也就是说,无论有没有显式定义,任何一个子类都有constructor方法。
通过super调用父类的方法时,super会绑定子类的this。
super看成函数调用时,表明父类的构造函数;super做为对象时,在普通方法中,指向父类的原型对象,在静态方法中,指向父类
26. http1.0 和 http2.0:
http2增长了:
27. use strict 严格模式:(参考文章:https://blog.csdn.net/weixin_40387601/article/details/80514358)
js 以更严谨的方式运行。
28. 小程序实现vue类型的数据监听:Object.defineProperty方法
/** * 设置监听器 */ setWatcher(page) { let data = page.data; let watch = page.watch; Object.keys(watch).forEach(v => { let key = v.split('.'); // 将watch中的属性以'.'切分红数组 let nowData = data; // 将data赋值给nowData for (let i = 0; i < key.length - 1; i++) { // 遍历key数组的元素,除了最后一个! nowData = nowData[key[i]]; // 将nowData指向它的key属性对象 } let lastKey = key[key.length - 1]; // 假设key==='my.name',此时nowData===data['my']===data.my,lastKey==='name' let watchFun = watch[v].handler || watch[v]; // 兼容带handler和不带handler的两种写法 let deep = watch[v].deep; // 若未设置deep,则为undefine this.observe(nowData, lastKey, watchFun, deep, page); // 监听nowData对象的lastKey }) }, /** * 监听属性 并执行监听函数 */ observe(obj, key, watchFun, deep, page) { var val = obj[key]; // 判断deep是true 且 val不能为空 且 typeof val==='object'(数组内数值变化也须要深度监听) if (deep && val != null && typeof val === 'object') { Object.keys(val).forEach(childKey=>{ // 遍历val对象下的每个key this.observe(val,childKey,watchFun,deep,page); // 递归调用监听函数 }) } var that = this; Object.defineProperty(obj, key, { configurable: true, enumerable: true, set: function(value) { // 用page对象调用,改变函数内this指向,以便this.data访问data内的属性值 watchFun.call(page,value,val); // value是新值,val是旧值 val = value; if(deep){ // 如果深度监听,从新监听该对象,以便监听其属性。 that.observe(obj, key, watchFun, deep, page); } }, get: function() { return val; } }) } page中使用: //index.js Page({ data: { my: { name: 'xuyang', age: 21, hobby: ['girls', 'games'] }, nameInfo:{} }, onLoad() { getApp().setWatcher(this); this.data.my.hobby[0] = 'study'; this.setData({ nameInfo:{name:'haha',sex:'boy'} }) console.log(this.data) }, watch: { my:{ handler(newValue) { console.log(newValue); }, deep:true } } })
(转载连接:https://blog.csdn.net/xuyangxinlei/article/details/81408200)
29. CSS 3 + HTML 5 (postcss-loader只是给 css 添加前缀,通gulp中的autoprefixer, 谨慎使用新属性)
1.选择器:
属性:[att=val] 指定特定名字的元素
[att*=val] 匹配val*的元素,
[att^=val] 匹配val开头的元素,好比id为val一、val432432均可以。
[att$=val] 匹配val结尾的元素,好比id为1213val、fdajlval等等。
顺序:first-child:选择第一个子元素
last-child:选择最后一个子元素
nth-child:选择第n个子元素,这个还能够根据奇偶来制定,
nth-last-child:选择倒数第n个子元素
only-child:单个子元素时,指定样式
状态: hover , active ,checked , selection, focus , enabled , disabled , read-only
2. 效果: border-radius , box-shadow , box-sizing , background属性 , linear-gradient , radial-gradient
3.动画:
1.关键帧动画:animation: name duration timing-function delay count; @keyframes
2.2D效果属性: tranform : translate 、rotate、scale ; transition
4. html5 :
1.语义化标签: nav ,head ,footer , aside,article,section;
2. 拖拽: drag , drop
3. vedio 、audio、canvas
4.input 新类型: time , date , email , url , search ,calendar , datetime, week , month , color , tel ,number ,
5. websocket , localstorage
28.闭包:定义 , 效果:能够获去操做一个函数中的局部变量。缺点:消耗内存,一直保持父函数的引用。 优势: 对局部变量保护做用,利于函数的 封装。
29. CMD,AMD比较:
AMD(异步模块定义):requirejs : 提早下载,提早执行
CMD(通用模块定义):seajs :提早下载,延迟执行
RequireJS 和 SeaJS 都是很不错的模块加载器,二者区别以下:
1. 二者定位有差别。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专一于 Web 浏览器端,同时经过 Node 扩展的方式能够很方便跑在 Node 服务器端
2. 二者遵循的标准有差别。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不一样,致使了二者 API 的不一样。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
3. 二者社区理念有差别。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,而采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
4. 二者代码质量有差别。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。
5. 二者对调试等的支持有差别。SeaJS 经过插件,能够实现 Fiddler 中自动映射的功能,还能够实现自动 combo 等功能,很是方便便捷。RequireJS 无这方面的支持。
6. 二者的插件机制有差别。RequireJS 采起的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采起的插件机制则与 Node 的方式一致:开放自身,让插件开发者可直接访问或修改,从而很是灵活,能够实现各类类型的插件。.
(来源文章:http://www.cnblogs.com/dojo-lzz/p/4707725.html)
30. arguments对象:函数的参数对象
特色:1. 不是数组,可是有数组的一些属性,length,索引,变成数组的方法:[].slice.call(arguments)或Array.prototype.slice.call(arguments);
typeof arguments // obeject ; {}.tostring.call(arguments) // [object Arguments]
2. 实参中的值和arguments中的值保持一致。
3. length的值不会自动改变,必须主动设置,但能够访问
4. 属性callee:arguments.callee指向函数自己,能够用于递归中,优势是即便函数名称改变,也不会报错 ; arguments.callee.caller指向调用此函数的函数,若无为null,
5. 严格模式下,对arguments操做,只对arguments有效,对参数无效。
function test(a,b,c){ console.log(c); arguments[2]=10; console.log(c); arguments[3]=10; console.log(arguments[3]); console.log(arguments.length); arguments.length=4; console.log(arguments.length); } test(1,2,3) // 结果: // 3 // 10 特色2 // 10 特色3 // 3 // 4 test(1,2) // 结果: // undefined 特色2 // 10 特色3 // 10 // 2 // 4
31. 队列,宏任务,微任务:参考:http://www.javashuo.com/article/p-cmtsxzha-h.html
1. 宏任务:script, setTimeout, setInterval :setTimeout 的含义为:xx毫秒后加入event loop 中,setInterval 也是如此。
微任务:promise.then, process.nextTick(): nextTick将执行函数添加至这次执行栈的尾部。
2. 执行顺序:script(宏) --> 微任务list(任务中有新的微任务时,直接添加在list中,依然在宏任务前执行) --> 宏任务list --> . . .
(宏任务必然是在微任务以后才执行的(由于微任务其实是宏任务的其中一个步骤))
32. SEO及优化:
1. TDK:title , description , keywords
2. 标题标签,img的alt属性,语义化标签,
SPA的优化:单页面应用对国内浏览器seo很不友好,国外浏览器不受影响。
a. 预渲染 b. ssr 服务端渲染,首屏采用服务端渲染。nuxt.js
vue : prerender-plugin + vue-meta-info
33. sort方法:浏览器的实现方式不一样:V8:<=22使用InsertionSort ,>22使用QuickSort排序。ff:归并排序
//自定义sort方法: Array.prototype.mySort = function (fn) { for (var i = this.length; i >0; i--) { for (var j =0; j < i; j++) { if (fn && typeof fn == 'function') { if(fn(this[j] ,this[j+1])>0){ [this[j], this[j+1]] = [this[j+1], this[j]]; } } else { var a = String(this[j]),b=String(this[j+1]); if(charcode(a,b)>0){ var temp=this[j]; this[j] = this[j+1]; this[j+1] = temp; // [this[j+1], this[j]] = [this[j], this[j+1]]; } } } } function charcode(a,b){ if(a.charCodeAt(0)<b.charCodeAt(0)){ return -1 }else if(a.charCodeAt(0)>b.charCodeAt(0)){ return 1 }else{ if(a.slice(1)===''){ return -1 }else if(b.slice(1)===''){ return 1 }else{ return charcode(a.slice(1),b.slice(1)) } } } return this; }
34. 构造函数:
//js中没有类的概念(es6中也只是中语法糖),因此经过原型链实现继承这种机制。 //构造函数实际上就是普通函数,返回一个实例对象 function Test(name,age){ this.name=name; this.age=age; }; //每一个函数都有prototype属性,一个对象,是因此实例对象共有的属性方法,由于都引用这个对象,new 的过程当中会自动添加constructor属性,构造函数自己。 Test.prototype.constructor = Test; Test.prototype.fn=function(){}; //一个实例的属性分为两部分:自有属性 + 公共属性 var test = new Test(1,2); // name , age , fn //经过 hasOwnProperty 判断属性是不是自有属性 test.hasOwnProperty('fn') // false //经过 isPrototypeOf 判断 实例 是不是构造函数的实例 Test.prototype.isPrototypeOf(test) // true;
35原型链:
数据类型:undefined,null,Number,String,Boolean + Object 六大类型。 Number,String,Boolean, Object,Function等都是构造函数,typeof 值:‘function’ 生成相应类型的数据能够直接定义,也能够经过构造函数生成(这种方式生成的返回值都是一个 object,function例外,返回的是function), // 1.prototype:只有函数有此属性, // 2.__proto__:对象的此属性指向构造函数的prototype, 函数的此属性指向Function的prototype(因此的函数都是Function的实例), Obeject.__proto__ === Function.prototype // true typeof 为function,此function较特殊,没有prototype属性, Object.__proto__.__proto__ ===Object.prototype // true 拥有object的属性 //constructor:指向构造函数自己,在34中,是在prototype中的默认一个属性。所以因此的实例中也会有此方法,
sd
36.运算符优先级及转换
var a = (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]] + ({}+[])[[~!+[]]*~+[]]; // sb (--的优先级大于*;~改变正负值再减一;[]是空=>0;{}是[object Object])
sd