题目一
- JS中使用typeof 能得到哪些类型
- 何时使用 === 何时使用==
- JS中有哪些内置函数
- JS变量按照存储方式区分为哪些类型,并描述其特点
- 如何理解JSON
JS按照存储方式分类分为哪几种类型:
- 引用类型:对象、数组、函数
- 特点:不限制属性,指针指向共同存储块,节省内存空间
- 值类型: 布尔、num、字符串、underfind
- 每个变量单独一个固定存储块
typeof运算符
-
typeof 只能区分值类型数据
- 引用类型的话只能分辨出函数(function),比较特殊
typeof undefined //undefined typeof 'abc' //string typeof 123 //number typeof true //boolean typeof {} //object typeof [] //object typeof null //object typeof console.log //function
值类型的变量计算:强制类型转换计算
- 字符串拼接
- 双等好==
- if语句
- 逻辑运算符 (&& 、 || 、 !)
何时用 === 何时用 ==
if(obj.a == null){
//这里相当于obj.a === null || obj.a=== underfind,简写形式
//这是jq源码中推荐的写法
//除了这个的判断,其余都建议使用===
}
js中的内置函数有哪些
- Object
- Array
- Boolean
- Number
- String
- Function
- Date
- RegExp
- Error
- 知道这个的用处就是为了今后学习构造函数使用
什么是json
//json 是js中的对象,类似Math,同时也是一种数据格式
// js给他内置了两个方法
JSON.Stringify({a:1,b:2}) //json转化为字符串
JSON.parse('{"a":1,"b":2}') //字符串转为json
题目二
- 如何判断一个变量是数组类型
- 写一个原型链继承的例子
- 描述new一个对象的过程
- zepto(或其他框架)源码中如何使用原型链
构造函数
function Per(name,age){
this.name = name;
this.age = age;
//return this 默认会返回this,这个this其实是一个对象
}
var a = new Per('zhangsan',20);
// 构造函数就类似一个模板,把一些相同属性和方法统一
// 代表着具有相同属性和方法的类的聚合
// 引用类型的值都具有构造函数,举例:
var a = {} //其实是var a = new Object()的语法糖
var a = [] //其实是var a = new Array()的语法糖
function Foo*(){...} //其实是 var Foo = new Function(...)
// 构造函数的首字母大写
原型规则和示例(掌握五个规则)
- 规则1:所有引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null” 意外)
- 规则2:所有引用类型(数组、对象、函数),都有一个
__proto__
(隐式原型)属性,属性值是一个普通的对象 - 规则3:所有的函数,都有一个prototype (显示原型)属性,属性值是一个普通对象
- 规则4: 所有引用类型(数组、对象、函数),
__proto__
属性值指向它的构造函数的“prototype” 属性值 - 规则5:当试图得到一个对象(引用类型)的属性的时候,如果这个对象没有这个属性,那么会去它的
__proto__
(隐式原型)(即它的构造函数的prototype)中寻找
//举例:对比规则1
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn () {}
fn.a = 100;
//举例:对比规则2
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
//举例:对比格则3
console.log(fn.prototype);
//举例:对比规则4
console.log(obj.__proto__ === Object.prototype) //true
//举例:对比规则5
//构造函数
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() //'zhangsan'
f.alertName() //'zhangsan'
循环对象自身的属性
//一般情况,f函数有三个属性,name/printName/alertName //要想拿到对象的自己的属性 var item; for (item in f) { //高级浏览器已经在 for in 中屏蔽了来自原型的属性 //但是这里建议大家加上这个判断,保证程序的健壮性 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() //'zhangsan'
f.alertName() //'zhangsan'
f.toString() //应该找 f.__proto__.__proto__
//首先找:f有没有toString 属性,没有找 f.__proto__ 即 Foo.prototype
//Foo.prototype是对象,也具有__proto__属性
//Foo.prototype.__proto__ 是指向Object.prototype
//Object.prototype 有toString()属性,截止
//在往上的话,js规定,Objcet.prototype.__proto__ 是null,截止
instanceof
-
是判断引用类型是属于哪个构造函数的方法
var a = []; var b = a instanceof Array; //判断是否是一个数组,引用类型的值用typeof不能判断 //举例 function Foo(name, age) { this.name = name } Foo.prototype.alertName = function () { alert(this.name) } //创建示例 var f = new Foo('zhangsan') var b = f instanceof Foo //判断f 的构造函数 是不是Foo //判断的逻辑是:f的__proto__一层一层往上,能否对应到Foo的prototype //再试着判断 f instanceof Object, 发现能够找到,也是true
写一个原型链继承的例子
//动物
function Animal() {
this.eat = function () {
console.log('animal eat')
}
}
//狗
function Dog() {
this.bark = function () {
console.log('dog bark')
}
}
Dog.prototype = new Animal()
//哈士奇
var hashiqi = new Dog()
//则哈士奇继承了dog的属性,以及bark的属性
//以上是小例子便于理解
//下面写的是贴近实战的例子
*****
描述new一个对象的过程
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//retuen this //默认有这个
}
var f = new Foo('zghangsan', 20)
var arr = new Array()
//首先创建一个空对象 this = {}
//this指向这个新的对象
//执行代码,即对this赋值
//返回this,即返回新创建的对象{}
zepto(或者其他框架)源码中如何使用原型链
- 阅读源码是高效提高技能的方式
- 慕课网搜索‘zepto设计和源码分析’,对于面试来说加分
//仿照类似jQuery,或者zepto 写一个简单的原型继承的例子
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.adEventListener(type, fn)
return this
}
var div1 = new Elem('div1')
//console.log(div1.html())
div1.html('<p>htllo world</p>').on('click', function(){
alert('clicked')
}).html('<p>javascript</p>')
题目三
- 说一下对变量提升的理解
- 说明this几种不同的使用场景
- 创建10个标签,点击的时候弹出来对应的序号
- 如何理解作用域
- 实际开发中闭包的应用
this
- this要在执行的时候才能确认值,定义时无法确认
var a = {
name: 'A',
fn: function () {
console.log(this.name)
}
}
a.fn //this === a
a.fn.call({name: 'B'}) //this === {name: 'B'}
var f1 = a.fn
f1() //this === window
-
几种this应用场景
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
function fn() { console.log(this) //这个this === window } fn()
-
call apply bind
bind得和函数声明联合一起用,最常用的是call
作用域和闭包
-
一个函数的父级作用域是看这个函数在哪里定义,不要看在哪里执行
-
闭包的使用场景,一下情况就是闭包
-
函数作为返回值
function F1() { var a = 100 retuen function () { console.log(a) //a是自由变量,父级作用域寻找 } } var f1 = F1() var a = 200 f1() //100
-
函数作为参数传递
function F1() { var a = 100 retuen function () { console.log(a) } } var f1 = fn() function F2(fn) { var a = 200 fn() } F2(f1) //100
-
-
实际开发中闭包的应用
//闭包实际应用中主要是用于封装变量、收敛权限 function isFirstLoad() { var _list = [] return function (id) { if (_list.indexOf(id) >= 0) { return false } else { _list.push(id) retuen true } } } //使用 var firstLoad = isFirstLoad() firstLoad(10) //true firstLoad(10) //false firstLoad(20) //true //闭包意义在于:你在isFirstLoad函数外面,根本不可能修改掉_list的值,把一些功能return出去,数据不能更改
-
解释自执行函数
var i for (i = 0; i < 10; i++) { //每执行一次循环,传一个i值进去,然后创建一个自执行函数,此时的i就变成函数作用域的值存储,总共创建10个函数即10个函数作用域 (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) }
题目四
- 同步和异步区别是什么?分别举一个同步和异步的例子
- 一个关于setTimeout的笔试题
- 前端使用异步的场景有哪些
异步
- 什么时候使用异步(需要等待的任务)
- 定时任务:setTimeout, setInterval
- 网络请求:ajax请求,动态
加载
- 事件绑定
数组API
-
forEach 遍历所有元素
-
every 判断所有元素是否都符合条件
-
some 判断是否有至少一个元素符合条件
-
sort 数组排序
-
map 对元素重新组装,生成新数组
-
filter 过滤符合条件的元素
// forEach var arr = [1,2,3] arr.forEach(function (item, index) { //遍历所有元素 console.log(index, item) }) //every var arr = [1,2,3] var result = arr.every(function (item, index) { //判断所有数组元素,都满足一个条件 if (item < 4) { return true } }) console.log(result) //sort var arr = [1,4,3,2,5] var arr2 = arr.sort(function (a, b) { //从小到大排序 return a - b //从大到小排序 //return b - a }) console.log(arr2) // map var arr = [1,2,3,4] var arr2 = arr.map(function (item, index) { //将元素重新组装返回 return '<b>' + item + '</b>' }) console.log(arr2) //filter var arr = [1,2,3] var arr2 = arr.filter(function (item, index) { //通过一个条件过滤数组 if (item >= 2) { return true } }) console.log(arr2)
对象API
-
for in
var obj = { x: 100, y: 200, z: 300 } var key for (key in obj) { //hasOwnProperty表示自有的属性 if (obj.hasOwnProperty(key)) { console.log(key, obj[key]) } }
写一个既能遍历对象也能遍历数组的forEach函数
