附注:慕课网还有一个JavaScript高级面试课程
1.前言
哪些部分?
JS基础、JS Web API、JS开发环境
问题:JS中使用typeof能得到哪些类型?
考点:JS变量类型
问题:何时使用===
何时使用==
?
考点:强制类型转换
问题:window.onload和DOMContentLoaded的区别?
考点:浏览器渲染过程
考点:作用域
问题:简述如何实现一个模块加载器,实现类似require.js的基本功能
考点:JS模块化
问题:实现数组的随机排序
考点:JS基础算法
2.JS基础知识-原型
讲解 JS 基础语法相关的面试题,分析原理以及解答方法。这一章节讲解了基础知识的第一部分:变量的类型和计算。以及JS “三座大山” —— 原型、作用域和异步中的第一座大山:原型。
2.1变量类型和计算
问题:
JS中使用typeof能得到哪些类型?
何时使用===
何时使用==
?
JS中有哪些内置函数?
JS变量按照存储方式区分为哪些类型,并描述其特点
如何理解JSON
知识点:
变量类型
变量计算
变量类型:
值类型(number、string、boolean、null、undefined、symbol)
引用类型(Object、Function、Array)
//值类型
var a = 100
var b = a
a = 200
console.log(b) // 100
//引用类型
var a = {age:20}
var b = q
b.age = 21
console.log(a.age) // 21
typeof运算详解
typeof运算符:
typeof 123 //number
typeof NaN //number
typeof 'abc' //string
typeof true //boolean
typeof undefined //undefined
typeof null //object
typeof {} //object
typeof [] //object
typeof console.log //function
所以,typeof只能区分值类型的类型,对于引用类型不能区分,但是可以区分函数。
附注typeof Object
返回值是function,因为Object是内置函数。
变量计算-强制类型转换
字符串拼接、==运算符、if语句、逻辑运算
var b = 100 + '10' // '10010'
100 == '100' //true
0 == '' //true
null == undefined //true
var b =100
if(b){
}
var c= ''
if(){
}
console.log(10 && 0) // 0
console.log('' || 'abc') //'abc'
console.log(!window.abc) //true (因为window.abc是undefined)
// 判断一个变量会被当成true还是false
var a = 100
console.log(!!a) //因为!a时候会进行强制类型转换,变成boolean类型,!!两个就是会转换成原始是true还是false
何时使用===
何时使用==
?
if (obj.a == null) {
// 这里相当于obj.a === null || obj.a === undefined,简写形式
// 这里是jQuery源码中推荐的写法
}
其他情况都用===
JS中有哪些内置函数?
数据封装类对象:
Number、String、Boolean、
Object、Array、Function、
Date、RegExp、Error
JS变量按照存储方式区分为哪些类型,并描述其特点
值类型、引用类型
如何理解JSON
JSON可以理解为JS对象,还有两个方法:
JSON字符串:
var jsonStr ='{"name":"Liza", "password":"123"}' ;
JSON对象:
var jsonObj = {"name":"Liza", "password":"123"};
1、JSON字符串转化JSON对象
var jsonObject= jQuery.parseJSON(jsonstr);
2、JSON对象转化JSON字符串
var jsonstr =JSON.stringify(jsonObject );
参考文章:https://blog.csdn.net/xujie3/article/details/52954940/
2.2原型和原型链
问题:
如何准确判断一个变量是数组类型
写一个原型链继承的例子
描述new一个对象的过程
zepto(或其他框架)源码中如何使用原型链
知识点:
构造函数
构造函数-扩展
原型规则和示例
原型链
instanceof(类型判断,原型链的一种体现)
构造函数
function Foo(name,age){
this.name = name
this.age = age
this.class = 'class-1'
return this //默认有这一行
}
var f = new Foo('zhangsan',20)
构造函数-扩展
var a = {}
a instanceof Object // true
var a = []
a instanceof Array // true
function Foo(){}
Foo instanceof Function //true
如何准确判断一个变量是数组类型?
所以根据上面截图和代码,知道判断一个变量是否为“数组”方法:变量 instanceof Array
var arr = []
arr instanceof Array //true
typeof Array //object typeof是无法判断是否是数组的
原型规则和示例
原型规则是学习原型链的基础:
1.所有引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null”意外)
2.所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象
3.所有的函数(可以理解构造函数),都有一个prototype属性,属性值也是一个普通的对象
4.所有的引用类型(数组、对象、函数),proto__属性值指向它的构造函数"prototype"属性值
5.当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto(即它的构造函数的prototype)中寻找
通过上图和构造函数知识可以知道:
var obj = {};
var arr = [];
function fn(){}
obj.__proto__ // Object
arr.__proto__ // Array
fn.__proto__ // Function
//第四条可以知道
obj.__proto__ === Object.prototype
第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 因为通过构造函数创建对象this指向创建的对象本身也就是f,此时代码就是alert(f.name),f有属性this.name,所以结果是zhangsan
循环对象自身的属性
//循环f中属性内容
for (item in f){
console.log(item)
}
name
printName
alertName
//循环对象自身的属性(hasOwnProperty)
for (item in f){
if(f.hasOwnProperty(item)){
console.log(item)
}
}
name
printName
原型链
f.toString() // 要去 f.__proto__.__proto__中查找
f.__proto__.__proto__ === Object.prototype //true
f.__proto__.__proto__.__proto__ //null,就是说Object.prototype再往上就没了,没有原型了
instanceof:用于判断引用类型属于哪个构造函数的方法
利用这一点和上图原型链,也可以判断原型链关系:
f instanceof Foo
true
f instanceof Object
true
Foo.prototype instanceof Object
true
f instanceof Foo的判断逻辑是:
f的__proto__一层一层往上,能否对应到Foo.prototype。
写一个原型链继承的例子
//动物
function Animal(){
this.eat = function(){
console.log('eat')
}
}
//狗
function Dog(){
this.bark = function(){
console.log('bark')
}
}
Dog.prototype = new Animal()
//哈士奇
var hashiqi = new Dog()
hashiqi.__proto__ === Dog.prototype
true
hashiqi.__proto__.__proto__ === Animal.prototype
true
比较专业的原型链继承的例子:
//写一个封装DOM查询的例子
function Elem(id){
this.elem = document.getElementById(id)
}
Elem.prototype.html = function(val){
var elem = this.elem
}
var div1 = new Elem('div1')
描述new一个对象的过程
1.创建一个新对象
2.this指向这个新对象
3.执行代码,即对this赋值
4.返回this
zepto(或其他框架)源码中如何使用原型链
阅读源码是高效提高技能的方式
3.JS基础知识-作用域和闭包
3.1函数声明和函数表达式
// 函数声明
function fn(){
}
// 函数表达式
var fn = function(){
}
3.2作用域和闭包
问题:
说一下对变量提升的理解
说明this几种不同的使用场景
创建10个标签,点击的时候弹出来对应的序号
如何理解作用域
实际开发中闭包的应用
知识点:
执行上下文
this
作用域
作用域链
闭包
执行上下文
this
this要在执行时才能确认值,定义时无法确认
(闭包中,变量要看定义的地方,不能看执行的地方)
1.作为普通函数执行
2.作为对象属性(方法)执行
3.作为构造函数执行
4.call apply bind
var a = {
name:'A',
fn:function(){
return this
}
}
// 通过方法调用
a.fn() === a
true
//通过函数调用
var fn1 = a.fn
fn1() === window
true
a.fn() === window
false
//通过call/apply调用
a.fn.call({name:'B'}) //this === {name:'B'}
//call apply bind
function fn1(name){
alert(name)
console.log(this)
}
fn1.call({x:100},'zhangsan') // {x:100} === this
var fn2 = function(name,age){
consloe.log(this)
}.bind({y:200})
fn2('zhangsan',20) //{y:200} === this
作用域
JavaScript没有块级作用域
只有函数和全局作用域
自由变量的概念:当前作用域没有定义的变量
闭包
this要在执行时才能确认值,定义时无法确认
(闭包中,变量要看定义的地方,不能看执行的地方)
function F1(){
var a = 100
//返回一个函数(函数作为返回值)
return function(){
console.log(a)
}
}
var f1 = new F1()
var a = 200
f1() // 100
a是自由变量,根据作用域链,去父级作用域去找,a=100
f1()虽然是全局作用域下定义/执行,但是变量要去定义的时候的作用域。
闭包的使用场景:
1.函数作为返回值
2.函数作为参数传递
function F1(){
var a = 100
//返回一个函数(函数作为返回值)
return function(){
console.log(a)
}
}
var f1 = new F1()
function F2(fn){
var a =200
fn()
}
F2(f1) // 100
注意注意下面代码:
//第一种可能
function F1(){
//var a = 100
//返回一个函数(函数作为返回值)
return function(){
console.log(a)
}
}
var f1 = new F1()
function F2(fn){
var a =200
fn()
}
var a = 300
F2(f1)
300
//第二种可能
function F1(){
//var a = 100
//返回一个函数(函数作为返回值)
return function(a1){
console.log(a1)
}
}
var f1 = new F1()
function F2(fn){
var a =200
fn(a)
}
F2(f1)
200
//第三种可能
function F1(){
var a = 100
//返回一个函数(函数作为返回值)
return function(a1){
console.log(a1)
}
}
var f1 = new F1()
function F2(fn){
var a =200
fn(a)
}
F2(f1)
200
说一下对变量提升的理解
变量定义、函数声明与函数表达式的区别
说明this几种不同的使用场景
普通函数、对象方法、构造函数、call apply bind
因为i是自由变量,所以我们需要去到外面去找,此时i已经是10了。
如何理解作用域
自由变量、作用域链,即自由变量的查找、闭包的两个场景
实际开发中闭包的应用
闭包实际应用中主要用于封装变量,收敛权限