以下代码输出什么?
let a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
let a = 3
fn2()
}
let a = 2
return fn3
}
let fn = fn1()
fn()
执行fn2时往上级作用域fn1中找a,由于let a = 2已经执行,所以a此时的状态是2。
递归实现斐波那契数列
subStr和subString的区别
传入第二个参数时,substr是从起始点截取某个长度的字符串
subStr(start, num) √
而substring是截取2个位置之间的字符串
subString(start, end)
splice与slice区别
splice(start,num,insert) 位置开始,删几个,插入什么 √
slice(start,end) 从哪到哪开始删
字符串拼接的常用方法
str1 + str2
模板字符串 `${str1} ${str2}`
把类数组对象arrayLike转换成数组
\[...arrayLike\]
写一个reverseStr函数,实现字符串逆序输出
return str.split{''}.reverse().join('')
实现数组arr从小到大排序
注意:sort会改变原数组
arr.sort((a, b) => a-b>0? 1 : -1)<br>
甚至可以简写成
arr.sort((a, b) => a-b)
实现数组arr中的对象,以age从小到大排序
arr.sort((v1, v2) => v1.age-v2.age)
实现fn函数,参数为数组,返回数组中正数的平方和
我的写法:
const fn = (arr) => {
let res = 0;
for(let val of arr) {
if(val > 0) res += val**2
}
return res
}
简单写法:
const fn = arr => arr.filter(v => v>0).reduce((res, v) => res + v**2 , 0)
写一个函数将对象的属性和值拼接为key1=value1&key2=value2形式的字符串
我用的for-in循环没有这个Object.keys()方便
function traverse(obj) {
return Object.keys(obj).map(key => `${key}=${obj[key]}`).join('&')
}
对象转换为JSON字符串&&JSON格式字符串转换为对象
JSON.stringify(obj)
JSON.parse(str)
清空一个数组的两种写法
arr = [] 本质上是创建一个新的空数组,让arr指向新的空数组
arr.length = 0 本质上是对原数组操作,让原数组变成空数组
以下代码输出什么
function inc(n){
console.log(++n)
}
let n = 10
inc(n)
console.log(n)
forEach()和map()的区别
forEach() 方法不会返回执行结果,而是修改原来的数组 map() 方法会得到一个新的数组并返回
深拷贝的简单写法
function deepCopy(src) {
return JSON.parse(JSON.stringify(src))
}
把字符串中的div标签替换成span标签
str.replace(/(<\/?)div(.*?>)/g, '$1span$2')
匹配一个字符,这个字符可以是'abc'中的任何一个
/[abc]/
匹配字符串"[abc]"
/\[abc\]/
以1为开头的长度为11位且全为数字的字符串
/^1\d{10}$/.test(str)
验证用户输入是否为合法密码。参数为字符串,返回值为布尔值
- 密码长度6~20位
- 密码只能是大小写字母、数字、下划线、$
- 大写、小写、数字、下划线、$至少包含两种
function validPassword(rawInput) {
if(!/^[\w\d$_]{6,20}$/.test(rawInput)) return false
if (/(^[a-z]+$)|(^[A-Z]+$)|(^\d+$)|(^_+$)|(^\$+$)/.test(rawInput))
return false
else return true
}
注意定时器是自动执行的,只有函数内放定时器才是调用后执行
原型链的顶端 Object.prototype
Array.__proto__.constructor
ƒ Function() { [native code] }
Function.__proto__.constructor
ƒ Function() { [native code] }
Function.prototype.__proto__.constructor
ƒ Object() { [native code] }
Object.__proto__.construtor
undefined
如何判断某属性是对象的自有属性
记得括号里加引号
[1,2].hasOwnProperty('sort')
false
[1,2].__proto__.hasOwnProperty('sort')
true
Array.hasOwnProperty('sort')
false
Array.prototype.hasOwnProperty('sort')
true
继承时this的指向问题
写一个函数 orderBy ,实现数组按姓名、年纪、任意字段按照设置对升降序排序
let users = [ { name: "Bob", age: 20, company: "Baidu" }, { name: "Cat", age: 18, company: "Alibaba" }, { name: "Ann", age: 19, company: "Tecent" }]
console.log( users.sort(orderBy('company', 'asc')) ) // company字段 以升序(从小到大)排序
console.log( users.sort(orderBy('age', 'desc')) ) //age 字段以降序(从大到小)排序
const orderBy = (field, order = 'asc') => (v1, v2) => {
if (order === 'asc') return v1[field] > v2[field] ? 1: -1
if (order === 'desc') return v1[field] > v2[field] ? -1: 1
}
两种绑定事件的方法
方法一:
$node.onclick = function() {...}
只能绑定一个事件监听函数,如果再次设置 .onclick,则会覆盖之前的绑定。因为本质上是给一个对象的onclick属性重新赋值;只能在事件冒泡阶段监听。
方法二:
document.body.addEventListener('click', function(){...})
可以针对click事件绑定多个事件监听函数;还有第三个参数,如果不设置,默认是false,表示在事件冒泡阶段监听。如果设置为true,表示在捕获阶段监听。
写一个函数 isAndroid,用来判断系统是不是安卓,返回 true/false
const isAndroid = () => /android/i.test(navigator.userAgent)
如何mock数据
手写server来mock数据 使用阿里团队的rap2来mock数据 使用大搜车前端团队的easy-mock (easy-mock.com/)来mock数据 使用Mock.js 来mock数据
loader 和 plugin 的区别
loader 用于对模块的源代码进行转换
loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript
loader 甚至允许你直接在 JavaScript 模块中 import CSS文件
plugin 用于解决loader无法实现的其他事,比如打包优化、压缩等
css-loader 能接收并处理css文件,并对css语法进行解析
style-loader 用于把css 注入到DOM
file-loader用于把里通过 import/require 引入的文件导出到目标文件夹,并且得到新的文件路径
在使用多个loader时顺序很重要,数组的最后一个最先接收并处理文件
关于HMR
模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面
模块热替换能保留在完全重新加载页面时丢失的应用程序状态
只更新变更内容,以节省宝贵的开发时间。
HMR 只能在开发环境中使用
调整样式更加快速 - 几乎相当于在浏览器调试器中更改样式
关于 treeshaking
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)
tree shaking 它依赖于ES2015模块语法的静态结构,即import和export
tree shaking 能减小代码体积,是性能优化的一种手段