背诵面试题
1、说说你对作用域链的理解
作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,
变量访问到
window
对象即被终止,作用域链向下访问变量是不被允许的
简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。
2、JavaScript原型,原型链 ? 有什么特点?
每个对象都会在其内部初始化一个属性,就是
__proto__
,当我们访问一个对象的属性时
如果这个对象内部不存在这个属性,那么他就会去
__proto__
里找这个属性,这个
__proto__
又会有自
己的
__proto__
,于是就这样一直找下去,也就是我们平时所说的原型链的概念。按照标准,
__proto__
是不对外公开的,也就是说是个私有属性
关系:
instance.constructor.prototype == instance.__proto__
特点:
JavaScript
对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型
副本。当我们修改原型时,与之相关的对象也会继承这一改变
当我们需要一个属性的时,
Javascript
引擎会先看当前对象中是否有这个属性, 如果没有的
就会查找他的
Prototype
对象是否有这个属性,如此递推下去,一直检索到
Object
内建对象
原型:
JavaScript
的所有对象中都包含了一个
[__proto__]
内部属性,这个属性所对应的就是该对象的原
型
JavaScript
的函数对象,除了原型
[__proto__]
之外,还预置了
prototype
属性
当 函 数 对 象 作 为 构 造 函 数 创 建 实 例 时 , 该
prototype
属 性 值 将 被 作 为 实 例 对 象 的 原 型
[__proto__]
。
原型链:
当一个对象调用的属性
/
方法自身不存在时,就会去自己
[__proto__]
关联的前辈
prototype
对象
上去找
如果没找到,就会去该
prototype
原型
[__proto__]
关联的前辈
prototype
去找。依次类推,直到
找到属性
/
方法或
undefined
为止。从而形成了所谓的
“
原型链
”
原型特点:
JavaScript
对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变
3、Javascript如何实现继承?
-
原型链继承:通过将子类型的原型设置为父类型的实例来实现。
-
构造函数继承:通过在子类型构造函数中调用父类型构造函数来继承属性和方法。
-
组合继承:将原型链和借用构造函数的技术组合在一起,使得子类型在实例化时调用了父类型的构造函数。
-
原型式继承:通过将传入对象的属性和方法添加到构造函数的原型上实现。
-
寄生式继承:通过基于已有的对象创建另一个对象,然后扩展此对象来实现继承。
-
类式继承:ES6引入了Class,通过extends关键字实现类式继承。
- 原型链继承:
-
function Parent() { this.name = 'parent'; } function Child() {} Child.prototype = new Parent();
- 构造函数继承
-
function Parent(name) { this.name = name; } function Child(name) { Parent.call(this, name); }
4、谈谈This对象的理解
this
总是指向函数的直接调用者(而非间接调用者)
如果有
new
关键字,
this
指向
new
出来的那个对象
var
a
=
{}
a
.
constructor
.
prototype
==
a
.
__proto__
在事件中,
this
指向触发这个事件的对象,特殊的是,
IE
中的
attachEvent
中的
this
总是指向全局对
象
Window
5、new操作符具体干了什么呢?
创建一个空对象,并且
this
变量引用该对象,同时还继承了该函数的原型
属性和方法被加入到
this
引用的对象中
新创建的对象由
this
所引用,并且最后隐式的返回
this
6、Ajax原理
Ajax
的原理简单来说是在用户和服务器之间加了
—
个中间层
(
AJAX
引擎
)
,通过
XmlHttpRequest
对象来
向服务器发异步请求,从服务器获得数据,然后用
javascrip
t
来操作
DOM
而更新页面。使用户操作与
服务器响应异步化。这其中最关键的一步就是从服务器获得请求数据
Ajax
的过程只涉及
JavaScript
、
XMLHttpRequest
和
DOM
。
XMLHttpRequest
是
aja
x
的核心机制
ajax
有那些优缺点
?
优点:
通过异步模式,提升了用户体验
.
优化了浏览器和服务器之间的传输,减少不必要的数据往返,减少了带宽占用
.
Ajax
在客户端运行,承担了一部分本来由服务器承担的工作,减少了大用户量下的服务器负载。
Ajax
可以实现动态不刷新(局部刷新)
缺点:
安全问题
AJAX
暴露了与服务器交互的细节。
对搜索引擎的支持比较弱。
不容易调试。
7、为什么要有同源限制?
同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议
举例说明:比如一个黑客程序,他利用
Iframe
把真正的银行登录页面嵌到他的页面上,当你使用真实
的用户名,密码登录时,他的页面就可以通过
Javascript
读取到你的表单中
input
中的内容,这样用
户名,密码就轻松到手了。
8、javascript有哪些方法定义对象
/** 1.
创建连接
**/
var
xhr
=
null
;
xhr
=
new
XMLHttpRequest
()
/** 2.
连接服务器
**/
xhr
.
open
(
'get'
,
url
,
true
)
/** 3.
发送请求
**/
xhr
.
send
(
null
);
/** 4.
接受请求
**/
xhr
.
onreadystatechange
=
function
(){
if
(
xhr
.
readyState
==
4
){
if
(
xhr
.
status
==
200
){
success
(
xhr
.
responseText
);
}
else
{
/** false **/
fail
&&
fail
(
xhr
.
status
);
}
}
}
对象字面量:
var obj = {}
;
构造函数:
var obj = new Object()
;
Object.create():
var obj = Object.create(Object.prototype)
;
9、说说你对promise的了解
依照
Promise/A+
的定义,
Promise
有四种状态:
pending:
初始状态
,
非
fulfilled
或
rejected.
fulfilled:
成功的操作
.
rejected:
失败的操作
.
settled: Promise
已被
fulfilled
或
rejected
,且不是
pending
另外,
fulfilled
与
rejected
一起合称
settled
Promise
对象用来进行延迟
(
deferred
)
和异步
(
asynchronous
)
计算
Promise
的构造函数
构造一个
Promise
,最基本的用法如下:
Promise
实例拥有
then
方法(具有
then
方法的对象,通常被称为
thenable
)。它的使用方法如下:
接收两个函数作为参数,一个在
fulfilled
的时候被调用,一个在
rejected
的时候被调用,接收参数
就是
future
,
onFulfilled
对应
resolve
,
onRejected
对应
reject
vue
、
react
、
angular
Vue.js
一个用于创建
web
交互界面的库,是一个精简的
MVVM
。它通过双向数据绑定把
View
层和
Model
层连接了起来。实际的
DOM
封装和输出格式都被抽象为了
Directives
和
Filters
AngularJS
是一个比较完善的前端
MVVM
框架,包含模板,数据双向绑定,路由,模块化,服务,依赖
注入等所有功能,模板功能强大丰富,自带了丰富的
Angular
指令
react React
仅仅是
VIEW
层是
facebook
公司。推出的一个用于构建
UI
的一个库,能够实现服务器端的
渲染。用了
virtual dom
,所以性能很好。
10、JS的基本数据类型和引用数据类型
基本数据类型:
undefined
、
null
、
boolean
、
number
、
string
、
symbol
引用数据类型:
object
、
array
、
function
11、介绍js有哪些内置对象
Object
是
JavaScript
中所有对象的父对象
数据封装类对象:
Object
、
Array
、
Boolean
、
Number
和
String
var
promise
=
new
Promise
(
function
(
resolve
,
reject
) {
if
(
...
) {
// succeed
resolve
(
result
);
}
else
{
// fails
reject
(
Error
(
errMessage
));
}
});
promise.then(onFulfilled, onRejected)
其他对象:
Function
、
Arguments
、
Math
、
Date
、
RegExp
、
Error
12、说几条写JavaScript的基本规范
不要在同一行声明多个变量
请使用
===/!==
来比较
true/false
或者数值
使用对象字面量替代
new Array
这种形式
不要使用全局函数
Switch
语句必须带有
default
分支
If
语句必须使用大括号
for
-
in
循环中的变量 应该使用
var
关键字明确限定作用域,从而避免作用域污
13、javascript创建对象的几种方式
javascript
创建对象简单的说
,
无非就是使用内置对象或各种自定义对象,当然还可以用
JSON
;但写
法有很多种,也能混合使用
对象字面量的方式
用
function
来模拟无参的构造函数
用
function
来模拟参构造函数来实现(用
this
关键字定义构造的上下文属性)
用工厂方式来创建(内置对象)
person
=
{
firstname
:
"Mark"
,
lastname
:
"Yun"
,
age
:
25
,
eyecolor
:
"black"
};
function
Person
(){}
var
person
=
new
Person
();
//
定义一个
function
,如果使用
new"
实例化
",
该
function
可以看作是
一个
Class
person
.
name
=
"Mark"
;
person
.
age
=
"25"
;
person
.
work
=
function
(){
alert
(
person
.
name
+
" hello..."
);
}
person
.
work
();
function
Pet
(
name
,
age
,
hobby
){
this
.
name
=
name
;
//this
作用域:当前对象
this
.
age
=
age
;
this
.
hobby
=
hobby
;
this
.
eat
=
function
(){
alert
(
"
我叫
"
+
this
.
name
+
",
我喜欢
"
+
this
.
hobby
+
",
是个程序员
"
);
}
}
var
maidou
=
new
Pet
(
"
麦兜
"
,
25
,
"coding"
);
//
实例化、创建对象
maidou
.
eat
();
//
调用
eat
方法
var
wcDog
=
new
Object
();
wcDog
.
name
=
"
旺财
"
;
wcDog
.
age
=
3
;
wcDog
.
work
=
function
(){
alert
(
"
我是
"
+
wcDog
.
name
+
",
汪汪汪
......"
);
}
wcDog
.
work
();
用原型方式来创建
用混合方式来创建
14、null,undefined 的区别
undefined
表示不存在这个值。
undefined
:
是一个表示
"
无
"
的原始值或者说表示
"
缺少值
"
,就是此处应该有一个值,但是还没有定
义。当尝试读取时会返回
undefined
例如变量被声明了,但没有赋值时,就等于
undefined
null
表示一个对象被定义了,值为
“
空值
”
null
:
是一个对象
(
空对象
,
没有任何属性和方法
)
例如作为函数的参数,表示该函数的参数不是对象;
在验证
null
时,一定要使用
===
,因为
==
无法分别
null
和
undefined
15、javascript 代码中的"use strict";是什么意思
use strict
是一种
ECMAscript 5
添加的(严格)运行模式
,
这种模式使得
Javascript
在更严格的条件下
运行
,
使
JS
编码更加规范化的模式
,
消除
Javascript
语法的一些不合理、不严谨之处,减少一些怪异行
为
16、JSON 的了解
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式
它是基于
JavaScript
的一个子集。数据格式简单
,
易于读写
,
占用带宽小
JSON
字符串转换为
JSON
对象
:
JSON
对象转换为
JSON
字符串:
var
obj
=
str
.
parseJSON
();
var
obj
=
JSON
.
parse
(
str
);
var last=obj.toJSONString();
var last=JSON.stringify(obj);
17、同步和异步的区别
同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求
,
等请求完,页面刷新,新内容出
现,用户看到新内容
,
进行下一步操作
异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内
容也会出现,用户看到新内容
18、谈谈你对ES6的理解
新增模板字符串(为
JavaScript
提供了简单的字符串插值功能)
箭头函数
for
-
of
(用来遍历数据
—
例如数组中的值。)
arguments
对象可被不定参数和默认参数完美代替。
ES6
将
p
romise
对象纳入规范,提供了原生的
Promise
对象。
增加了
let
和
const
命令,用来声明变量。
增加了块级作用域。
let
命令实际上就增加了块级作用域。
还有就是引入
module
模块的概念
19、ECMAScript6 怎么写class么
这个语法糖可以让有
OOP
基础的人更快上手
js
,至少是一个官方的实现了
但对熟悉
js
的人来说,这个东西没啥大影响;一个
Object.creat()
搞定继承,比
class
简洁清晰的多
20、什么是面向对象编程及面向过程编程,它们的异同和优缺点
面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个
一个依次调用就可以了
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙
某个事物在整个解决问题的步骤中的行为
面向对象是以功能来划分问题,而不是步骤
21、面向对象编程思想
基本思想是使用对象,类,继承,封装等基本概念来进行程序设计
优点
易维护
采用面向对象思想设计的结构,可读性高,由于继承的存在,即使改变需求,那么维护也只是
在局部模块,所以维护起来是非常方便和较低成本的
易扩展
开发工作的重用性、继承性高,降低重复工作量。
缩短了开发周期
22、如何通过JS判断一个数组
instanceof
方法
instanceof
运算符是用来测试一个对象是否在其原型链原型构造函数的属性
constructor
方法
constructor
属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数
var
arr
=
[];
arr
instanceof
Array
;
// true
最简单的方法
这种写法,是
jQuery
正在使用的
ES5
新增方法
isArray()
23、谈一谈let与var的区别
let
命令不存在变量提升,如果在
let
前使用,会导致报错
如果块区中存在
let
和
const
命令,就会形成封闭作用域
不允许重复声明,因此,不能在函数内部重新声明参数
24、map与forEach的区别
forEach
方法,是最基本的方法,就是遍历与循环,默认有
3
个传参:分别是遍历的数组内容
item
、数
组索引
index
、和当前遍历数组
Array
map
方法,基本用法与
forEach
一致,但是不同的,它会返回一个新的数组,所以在
callback
需要有
return
值,如果没有,会返回
undefined
25、谈一谈箭头函数与普通函数的区别?
函数体内的
this
对象,就是定义时所在的对象,而不是使用时所在的对象
不可以当作构造函数,也就是说,不可以使用
new
命令,否则会抛出一个错误
不可以使用
arguments
对象,该对象在函数体内不存在。如果要用,可以用
Rest
参数代替
不可以使用
yield
命令,因此箭头函数不能用作
Generator
函数
26、JS 数组和对象的遍历方式,以及几种方式的比较
for in
循环
for
循环
forEach
这里的
forEach
回调中两个参数分别为
value
,
index
forEach
无法遍历对象
IE
不支持该方法;
Firefox
和
chrome
支持
forEach
无法使用
break
,
continue
跳出循环,且使用
return
是跳过本次循环
这两种方法应该非常常见且使用很频繁。但实际上,这两种方法都存在性能问题
在方式一中,
for
-
in
需要分析出
array
的每个属性,这个操作性能开销很大。用在
key
已知的数组上
是非常不划算的。所以尽量不要用
for
-
in
,除非你不清楚要处理哪些属性,例如
JSON
对象这样的情况
var
arr
=
[];
arr
.
constructor
==
Array
;
//true
Object
.
prototype
.
toString
.
call
(
value
)
==
'[object Array]'
//
利用这个方法,可以写一个返回数据类型的方法
var
isType
=
function
(
obj
) {
return
Object
.
prototype
.
toString
.
call
(
obj
).
slice
(
8
,
-
1
);
}
var
a
=
new
Array
(
123
);
var
b
=
new
Date
();
console
.
log
(
Array
.
isArray
(
a
));
//true
console
.
log
(
Array
.
isArray
(
b
));
//false
在方式
2
中,循环每进行一次,就要检查一下数组长度。读取属性(数组长度)要比读局部变量慢,
尤其是当
array
里存放的都是
DOM
元素,因为每次读取都会扫描一遍页面上的选择器相关元素,速度
会大大降低
27、说一下Vue的双向绑定数据的原理
vue.js
则是采用数据劫持结合发布者
-
订阅者模式的方式,通过
Object.defineProperty()
来劫持各个
属性的
setter
,
getter
,在数据变动时发布消息给订阅者,触发相应的监听回调
28、let var const
let
允许你声明一个作用域被限制在块级中的变量、语句或者表达式
let
绑定不受变量提升的约束,这意味着
let
声明不会被提升到当前
该变量处于从块开始到初始化处理的
“
暂存死区
”
var
声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量
总是等效于在代码开头声明
const
声明创建一个值的只读引用
(
即指针
)
基本数据当值发生改变时,那么其对应的指针也将发生改变,故造成
const
申明基本数据类型时
再将其值改变时,将会造成报错, 例如
const a = 3
;
a = 5
时 将会报错
但是如果是复合类型时,如果只改变复合类型的其中某个
Value
项时, 将还是正常使用
29、JavaScript的组成
JavaScript
由以下三部分组成:
ECMAScript
(核心):
JavaScript`
语言基础
DOM
(文档对象模型):规定了访问
HTML
和
XML
的接口
BOM
(浏览器对象模型):提供了浏览器窗口之间进行交互的对象和方法
30、介绍JS有哪些内置对象
数据封装类对象:
Object
、
Array
、
Boolean
、
Number
、
String
其他对象:
Function
、
Arguments
、
Math
、
Date
、
RegExp
、
Error
ES6
新增对象:
Symbol
、
Map
、
Set
、
Promises
、
Proxy
、
Reflect
31、说几条写JavaScript的基本规范
代码缩进,建议使用
“
四个空格
”
缩进
代码段使用花括号
{}
包裹
语句结束使用分号
;
变量和函数在使用前进行声明
以大写字母开头命名构造函数,全大写命名常量
规范定义
JSON
对象,补全双引号
用
{}
和
[]
声明对象和数组
32、解释JavaScript中的作用域与变量声明提升
JavaScript
作用域:
在
Java
、
C
等语言中,作用域为
for
语句、
if
语句或
{}
内的一块区域,称为作用域;
而在
JavaScript
中,作用域为
function(){}
内的区域,称为函数作用域。
JavaScript
变量声明提升:
在
JavaScript
中,函数声明与变量声明经常被
JavaScript
引擎隐式地提升到当前作用域的顶部。
声明语句中的赋值部分并不会被提升,只有名称被提升
函数声明的优先级高于变量,如果变量名跟函数名相同且未赋值,则函数声明会覆盖变量声明
如果函数有多个同名参数,那么最后一个参数(即使没有定义)会覆盖前面的同名参数
33、列举一下JavaScript数组和对象有哪些原生方法?
数组:
arr.concat(arr1, arr2, arrn)
;
arr.join(",")
;
arr.sort(func)
;
arr.pop()
;
arr.push(e1, e2, en)
;
arr.shift()
;
unshift(e1, e2, en)
;
arr.reverse()
;
arr.slice(start, end)
;
arr.splice(index, count, e1, e2, en)
;
arr.indexOf(el)
;
arr.includes(el)
;
// ES6
对象:
object.hasOwnProperty(prop)
;
object.propertyIsEnumerable(prop)
;
object.valueOf()
;
object.toString()
;
object.toLocaleString()
;
Class.prototype.isPropertyOf(object)
;
34、Array.slice() 与 Array.splice() 的区别?
slice
“
读取
”
数组指定的元素,不会对原数组进行修改
语法:
arr.slice(start, end)
start
指定选取开始位置(含)
end
指定选取结束位置(不含)
splice
“
操作
”
数组指定的元素,会修改原数组,返回被删除的元素
语法:
arr.splice(index, count, [insert Elements])
index
是操作的起始位置
count = 0
插入元素,
count > 0
删除元素
[insert Elements]
向数组新插入的元素
35、MVVM
MVVM
由以下三个内容组成
View
:界面
Model
:数据模型
ViewModel
:作为桥梁负责沟通
View
和
Model
36、this指向
1
、
this
指向有哪几种
默认绑定:全局环境中,
this
默认绑定到
window
隐式绑定:一般地,被直接对象所包含的函数调用时,也称为方法调用,
this
隐式绑定到该直接对象
隐式丢失:隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到
window
。显式绑定:通过
call()
、
apply()
、
bind()
方法把对象绑定到
this
上,叫做显式绑定
new
绑定:如果函数或者方法调用之前带有关键字
new
,它就构成构造函数调用。对于
this
绑定来说,
称为
new
绑定
构造函数通常不使用
return
关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,
它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值
如果构造函数使用
return
语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回
值,同时使用这个新对象作为调用结果
如果构造函数显式地使用
return
语句返回一个对象,那么调用表达式的值就是这个对象
2.
改变函数内部
this
指针的指向函数(
bind
,
apply
,
call
的区别)
apply
:调用一个对象的一个方法,用另一个对象替换当前对象。例如:
B.apply(A, arguments)
;
即
A
对象应用
B
对象的方法
call
:调用一个对象的一个方法,用另一个对象替换当前对象。例如:
B.call(A, args1,args2)
;
即
A
对象调用
B
对象的方法
bind
除了返回是函数以外,它的参数和
call
一样
3.
箭头函数
箭头函数没有
this
,所以需要通过查找作用域链来确定
this
的值,这就意味着如果箭头函数被非箭头
函数包含,
this
绑定的就是最近一层非箭头函数的
this
,
箭头函数没有自己的
arguments
对象,但是可以访问外围函数的
arguments
对象
不能通过
new
关键字调用,同样也没有
new.target
值和原型