慕课网前端JavaScript面试(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014465934/article/details/88076433

附注:慕课网还有一个JavaScript高级面试课程

1.前言

哪些部分?
JS基础、JS Web API、JS开发环境

问题:JS中使用typeof能得到哪些类型?

考点:JS变量类型

问题:何时使用===何时使用==

考点:强制类型转换

问题:window.onload和DOMContentLoaded的区别?

考点:浏览器渲染过程

问题:用JS创建10个<a>标签,点击的时候弹出来对应的序号

考点:作用域

问题:简述如何实现一个模块加载器,实现类似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)

构造函数-扩展

在这里插入图片描述
所以通过上面截图可以知道instanceof用法:

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个<a>标签,点击的时候弹出来对应的序号
如何理解作用域
实际开发中闭包的应用

知识点:
执行上下文
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

创建10个<a>标签,点击的时候弹出来对应的序号

在这里插入图片描述
因为i是自由变量,所以我们需要去到外面去找,此时i已经是10了。

在这里插入图片描述

如何理解作用域

自由变量、作用域链,即自由变量的查找、闭包的两个场景

实际开发中闭包的应用

闭包实际应用中主要用于封装变量,收敛权限

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u014465934/article/details/88076433