interview
js 基础
原型 原型链
作用域 闭包
异步 单线程
js Api dom 操作 ajax 事件绑定
版本管理 模块化 打包工具
题
- js 中使用 typeof 能得到哪些类型 (js 变量类型)
typeof undefined //undefined
typeof 'abc' //string
typeof 123 //number
typeof true //object
typeof {} //object
typeof [] //object
typeof null //object
typeof console.log //function
- 何时用=== 何时使用==(强制类型转换)
//除了这两种其他都用===
if (obj.a == null) {
//这里相当于obj.a===null ||obj.a===undefined 简写
//这是jquery源码推荐写法
}
function(a,b){
if(a==null){
}
}
- 字符串拼接
var a = 100 + 10 //110
var a = 100 + '10' //'10010'
- ==运算符
100 == '100' //true
0 == '' //true 0和空字符串都转换成false
null == undefined //true
- if 语句
var a = true
if (a) {
}
var b = 100 //转换成bool true
if (b) {
}
if ('') {
//false
}
if (0) {
//false
}
if (null) {
//false
}
if (NaN) {
//false
}
if (false) {
//false
}
if (undefined) {
//false
}
- 逻辑运算 与或非
console.log(100 && 0) //0 100换成了true
console.log('' || 'abc') //'abc'
console.log(!window.abc) //true
//判断一个变量会被当做true 还是false
var a = 100
console.log(!!a)
- js 有哪些内置函数
Object
Array
Boolean
Number
String
Function
Date
RegExp
Error
- js 变量按照存储方式区分为哪些类型
// 值类型
var a = 10
var b = a
a = 11
console.log(b) //10
// 引用类型 :对象、数组、函数
var obj1 = { x: 100 }
var obj2 = obj1
obj1.x = 200
console.log(obj2.x) //200
- 如何理解 JSON
//JSON只是一个js对象而已
//从一个对象解析出字符串
JSON.stringify({ a: 10, b: 20 }) //{"a":10,"b":20}
//parse用于从一个字符串中解析出json对象如
JSON.parse('{"a":10,"b":20}') //{a:10,b:20}
//注意:对象名必须用双引号 {}使用单引号包裹
原型和原型链
构造函数
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this
}
var f = new Foo('zhangsan', 20)
//var f1=new Foo('lisi',22)
构造函数-扩展
var a ={} 其实是 var a =new Object()的语法糖
var a =[] 其实是 var a =new Array()的语法糖
function Foo(){..}其实是 var Foo =new Function(...)
使用 instanceof 判断一个函数是否是一个变量的构造函数
原型规则和示例
- 所有的引用类型(数组、对象、函数),都具有对象特性,既可自由扩展属性(除了“null”外)
var obj = {}
obj.a = 20
var arr = []
arr.a = 10
function fn() {}
fn.a = 100
- 所有的引用类型(数组、对象、函数),都有一个
__proto__
(隐式原型)属性,属性值是一个普通对象
console.log(obj.__proto__)
console.log(arr.__proto__)
console.log(fn.__proto__)
- 所有的函数,都有一个 prototype(显示原型) 属性,属性值是一个普通对象
console.log(fn.prototype)
- 所有的引用类型(数组、对象、函数),都有一个
__proto__
属性值指向它的构造函数的“prototype”属性值
console.log(obj.__proto__ === Object.prototype)
- 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的
__proto__
(既它的构造函数的 prototype)去寻找
//构造函数
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function() {
alert(this.name)
}
//创建实例
var f = new Foo('zhangsan')
f.printName = function() {
console.log(this.name)
}
//测试
f.printName()
f.alertName()
for (var item in f) {
if (f.hasOwnProperty(item)) {
console.log(item)
}
}
原型链
//构造函数
function Foo(name, age) {
this.name = name
}
Foo.prototype.alertName = function() {
alert(this.name)
}
//创建实例
var f = new Foo('zhangsan')
f.printName = function() {
console.log(this.name)
}
//测试
f.printName()
f.alertName()
f.toString() //要去f.__proto__.__proto__中查找
)
[图片上传失败...(image-531d0f-1571457332167)]
- instanceof 用于判断引用类型属于哪个构造函数的方法
f instanceof Foo
题
- 如何准确判断一个变量是数组类型
var arr = []
arr instanceof Array //true
typeof arr //object 无法判断是否时数组
- 写一个原型链继承的例子
- 用于理解
//动物
function Animal() {
this.eat = function() {
console.log('animal eat')
}
}
//狗
function Dog() {
this.bark = function() {
console.log('this bark')
}
}
Dog.prototype = new Animal()
//哈士奇
var hashiqi = new Dog()
hashiqi.eat()
hashiqi.bark()
- 用于面试
function Elem(id) {
this.elem = document.getElementById(id)
}
Elem.prototype.html = function(val) {
var elem = this.elem
if (val) {
elem.innerHTML = val
return this //链式操作
} else {
return elem.innerHTML
}
}
Elem.prototype.on = function(type, fn) {
var elem = this.elem
elem.addEventListener(type, fn)
}
var div1 = new Elem('div1')
// console.log(div1.html())
div1
.html('<p>hello hihi</p>')
.on('click', function() {
alert('clicked')
})
.html('<p>javascrip</p>')
- 描述 new 一个对象的过程
创建一个新对象
this 指向这个新对象
执行代码 即对 this 赋值
返回 this
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this
}
var f = new Foo('zhangsan', 20)
- zepto(或其他框架)源码中如何使用原型链
- 阅读源码是高效提高技能的方式 zepto 设计与源码分析 jquery
作用域与闭包
执行上下文
范围:一段
<script>
或者一个函数全局:变量定义、函数声明
-
函数:变量定义、函数声明、this、arguments
PS:注意“函数声明”和“函数表达式”的区别
console.log(a) //undefined
var a = 100
fn('zhangsan') //'zhangsan' 20
//函数声明
function fn(name) {
age = 20
console.log(name, age)
var age
}
this
- 作为构造函数执行
function Foo(name) {
this.name = name
}
var f = new Foo('zhangsan')
- 作为对象属性执行
//函数表达式
var obj = {
name: 'A',
printName: function() {
consolo.log(this.name)
}
}
obj.printName() //this===abj
- 作为普通函数执行
var fn1 = a.fn
fn1() //this===window
- call apply bind
//this要在执行时确定值,定义时无法确认
var a = {
name: 'A',
fn: function() {
console.log(this.name)
}
}
a.fn() //this===a
a.fn.call({ name: 'B' }) //this==={name:'B'}
var fn1 = a.fn
fn1() //this===window
作用域
- js 没有块级作用域
if (true) {
var name = 'zhangsan'
}
console.log(name) //true
- 只有函数作用域和全局作用域
var a = 100
function fn() {
var a = 200
console.log('fn', a) //200
}
console.log('global', a) //100
fn()
- 作用域链
var a = 100
function fn() {
var b = 200
function fn2() {
var c = 300
//当前作用域没有定义的变量,既“自由变量”
console.log(a) //100自由变量
console.log(b) //200自由变量
console.log(c)
}
}
fn()
题
- 说一下对变量提升的理解(执行上下文)
变量定义
函数声明(注意与函数表达式的区别)
说明 this 几种不同的使用场景(this)
用 js 创建 10 个
<a>
标签 点击的时候弹出来对应的序号(作用域)
var i
for (i = 0; i < 10; i++) {
;(function(i) {
var a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
- 如何理解作用域(作用域)
自由变量
作用域链 自由变量的查找
闭包的两个场景
- 实际开发中闭包的应用(闭包)
function isFristLoad() {
var _list = []
return function(id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
//使用
var firstLoad = isFirstLoad()
firstLoad(10) //true
firstLoad(10) //false
firstLoad(20) //true
异步和单线程
异步
在可能发生等待的情况
等待的过程中不能像 alert 一样阻塞程序执行
定时任务: setTimeout setInverval
网络请求: ajax 请求 动态<img>加载
事件绑定
console.log(100)
setTimeout(function() {
console.log(200)
}, 1000)
console.log(300)
//100 300 200异步 不阻塞
console.log(100)
alert(200)
console.log(300)
//同步100 200 300
题
- 异步和同步的区别是什么 ? 分别举一个同步和异步的例子
同步会阻塞代码执行,而异步不会
alert 是同步。setTimeout 是异步
- 一个关于 setTimeout 的笔试题
console.log(1)
setTimeout(function() {
console.log(2)
}, 0)
console.log(3)
setTimeout(function() {
console.log(4)
}, 1000)
console.log(5) //1 3 5 2 4
- 前端使用异步的场景有哪些
定时任务: setTimeout setInverval
网络请求: ajax 请求 动态<img>加载
事件绑定
日期
Date.now() //获取当前时间毫秒数
var dt = new Date()
dt.getTime() //获取毫秒数
dt.getFullYear() //年
dt.getMonth() //月
dt.getDate() //日
dt.getHours() //小时
dt.getMinutes() //分钟
dt.getSeconds() //秒
Math
- 获取随机数 Math.random()
数组 API
- forEach 遍历所有元素
var arr = []
arr.forEach(function(item, index) {
console.log(index, item)
})
- every 判断所有元素是否都符合条件
var arr = []
var result = arr.every(function(item, index) {
if (item < 4) {
return true
}
})
console.log(result)
- some 判断是否有至少一个元素符合条件
var arr = []
var result = arr.some(function(item, index) {
if (item < 2) {
return true
}
})
console.log(result)
- sort 排序
var arr = [1, 6, 3, 5]
var arr2 = arr.sort(function(a, b) {
return a - b
}) //[1, 3, 5, 6]
- 对象 API
var obj = {
x: 100,
y: 200,
z: 300
}
var key
for (key in obj) {
if (obj.hasOwnProperty(key)) {
console.log(kay, obj[key])
}
}
map 对元素重新组装,生成新数组
filter 过滤符合条件的元素
获取 2017-06-10 格式的日期
function formatDate(dt) {
if (!dt) {
dt = new Date()
}
var year = dt.getFullYear()
var month = dt.getMonth() + 1
var date = dt.getDate()
if (month < 10) {
month = '0' + month
}
if (date < 10) {
date = '0' + date
}
return year + '-' + month + '-' + date
}
var dt = new Date()
var formaDate = formatDate(dt)
console.log(formatDate)
- 获取随机数,要求是长度一致的字符串格式
var random = Math.random()
var random = random + '0000000000'
var random = random.slice(0, 10)
console.log(random)
- 写一个能遍历对象和数组的通用 forEach 函数
function forEach(obj, fn) {
var key
if (obj instanceof Array) {
//准确判断是不是数组
obj.forEach(function(item, index) {
fn(index, item)
})
} else {
//不是数组就是对象
for (key in obj) {
fn(key, obj[key])
}
}
}
var arr = [1, 2, 3]
forEach(arr, function(index, item) {
console.log(index, item)
})
var obj = { x: 100, y: 200 }
forEach(obj, function(key, value) {
console.log(key, value)
})