1. split() join()的区别
- join():用于把
数组
中的所有元素
通过指定的分隔符
进行分隔放入一个字符串
- split():用于把一个
字符串
通过指定的分隔符
进行分隔成数组
2.JavaScript 的数据类型
String、Number、Boolean、Null、Undefined 和 Object
-
ES6
新增了Symbol
类型 -
Object
是引用类型
,其他的都是基本类型
(Primitive Type)。
3.如何判断一个对象是否属于某个类?
instanceof
if (a instanceof Person) {
alert("yes");
}
4.new 操作符具体干了什么呢?
new 共经过了 4 个阶段
1). 创建一个空对象
2). 设置原型链
3). 让 Func 中的 this 指向 obj,并执行 Func 的函数体
4). 判断 Func 的返回值类型:
function Test(){}
const test = new Test()
- 创建一个新对象:
const obj = {}
- 设置新对象的
constructor
属性为构造函数
的名称,设置新对象的proto
属性指向构造函数
的prototype
对象
obj.constructor = Test
obj.__proto__ = Test.prototype
- 使用新对象调用函数,函数中的 this 被指向新实例对象
Test.call(obj)
- 将初始化完毕的新对象地址,保存到等号左边的变量中
5.call() 和 apply() 的含义和区别?
call
:调用一个对象
的一个方法,用另一个对象
替换当前对象
apply
:调用一个对象
的一个方法,用另一个对象
替换当前对象
call与 apply的相同点:
方法的含义是一样的,即方法功能是一样的;
第一个参数的作用是一样的;
call与apply的不同点:
两者传入的列表形式不一样
call
可以传入多个
参数;apply
只能传入两个
参数,所以其第二个参数往往是作为数组形式
传入
6.sort 排序原理
冒泡排序法的原理:
比较
相邻的元素
。如果第一个比第二个大,就交换他们两个。对每一对
相邻元素
做同样的工作,从开始第一对
到结尾的最后一对
。在这一点,最后的元素应该会是最大
的数。针对所有的元素重复以上的步骤,除了
最后一个
。持续每次对越来越少的元素
重复
上面的步骤,直到没有任何一对数字
需要比较。
1.升序
var apple = [45, 42, 10, 147, 7, 65, -74];
// ①默认法,缺点:只根据首位排序
console.log(apple.sort());
// ②指定排序规则法,return可返回任何值
console.log(
apple.sort(function(a, b) {
return a - b; //若return返回值大于0(即a>b),则a,b交换位置
})
);
2.降序
var arr = [45, 42, 10, 111, 7, 65, -74];
console.log(
apple.sort(function(a, b) {
return b - a; //若return返回值大于零(即b>a),则a,b交换位置
})
);
7.如何判断当前脚本运行在浏览器还是 node 环境中?
通过判断Global
对象是否为window
,如果不为window
,当前脚本没有运行在浏览器
中
8.移动端最小触控区域是多大?
苹果推荐是 44pt x 44pt
9.移动端的点击事件的有延迟,时间是多久,为什么会有? 怎么解决这个延时?
300 毫秒
因为
浏览器
捕获第一次单击后,会先等待一段时间,如果在这段时间区间里用户未进行下一次点击,则浏览器
会做单击事件
的处理。如果这段时间里用户进行了第二次单击
操作,则浏览器
会做双击事件
处理。推荐
fastclick.js
10.解释 JavaScript 中的作用域与变量声明提升?
作用域
只会对某个范围
产生作用,而不会对外产生影响的封闭空间。在这样的一些空间里,外部
不能访问内部变量
,但内部
可以访问外部变量
所有申明都会被提升到作用域的
最顶
上同一个
变量申明
只进行一次
,并且因此其他申明都会被忽略函数声明的
优先级
优于变量申明
,且函数声明会连带定义
一起被提升
11.Node.js 的适用场景?
RESTFUL API
、实时聊天
、客户端逻辑强大的单页 APP
,
本地化的在线音乐应用
,本地化的在线搜索应用
,本地化的在线 APP
等。
12.bind、call、apply 的区别
call
和 apply
其实是一样的,区别就在于传参
时参数是一个一个传或者是以一个数组
的方式来传。
call
和apply
都是在调用时
生效,改变调用者的 this 指向
let name = 'Jack'
const obj = {name: 'Tom'}
function sayHi() {console.log('Hi! ' + this.name)}
sayHi() // Hi! Jack
sayHi.call(obj) // Hi! Tom
-
bind
也是改变this 指向
,不过不是在调用时生效,而是返回一个新函数
const newFunc = sayHi.bind(obj)
newFunc() // Hi! Tom
13.使用构造函数的注意点
一般情况下构造函数
的首字母需要大写,因为我们在看到一个函数首字母大写的情况,就认定这是一个构造函数
,需要跟new
关键字进行搭配使用,创建一个新的实例(对象)
构造函数
在被调用的时候需要跟new关键字搭配使用。在
构造函数
内部通过this+属性名
的形式为实例添加一些属性和方法。构造函数
一般不需要返回值,如果有返回值如果返回值是一个基本
数据类型
,那么调用构造函数
,返回值仍旧是那么创建出来的对象。如果返回值是一个
复杂数据类型
,那么调用构造函数
的时候,返回值就是这个return
之后的那个复杂数据类型
14.如何获取浏览器版本信息
window.navigator.userAgent
15.数组的常用方法
Array.map()
- 将数组中的每个元素调用一个提供的函数,结果作为一个新的数组返回,并没有改变原来的数组
let arr = [1, 2, 3, 4, 5];
let newArr = arr.map(x =› x * 2);
//arr= [1, 2, 3, 4, 5] 原数组保持不变
//newArr = [2, 4, 6, 8, 10] 返回新数组
Array.forEach()
- 将数组中的每个元素执行传进提供的函数,没有返回值,直接改变原数组,注意和 map 方法区分
let arr = [1, 2, 3, 4, 5];
num.forEach(x =› x * 2);
// arr = [2, 4, 6, 8, 10] 数组改变,注意和map区分
Array.filter()
- 将所有元素进行判断,将满足条件的元素作为一个新的数组返回
let arr = [1, 2, 3, 4, 5]
const isBigEnough =› value =› value ›= 3
let newArr = arr.filter(isBigEnough )
//newNum = [3, 4, 5] 满足条件的元素返回为一个新的数组
Array.every()
- 将所有元素进行判断返回一个布尔值,如果所有元素都满足判断条件,则返回 true,否则为 false:
let arr = [1, 2, 3, 4, 5]
const isLessThan4 =› value =› value ‹ 4
const isLessThan6 =› value =› value ‹ 6
arr.every(isLessThan4 ) //false
arr.every(isLessThan6 ) //true
Array.some()
- 将所有元素进行判断返回一个布尔值,如果存在元素都满足判断条件,则返回 true,若所有元素都不满足判断条件,则返回 false:
let arr= [1, 2, 3, 4, 5]
const isLessThan4 =› value =› value ‹ 4
const isLessThan6 =› value =› value › 6
arr.some(isLessThan4 ) //true
arr.some(isLessThan6 ) //false
Array.reduce()
- 所有元素调用返回函数,返回值为最后结果,传入的值必须是函数类型:
let arr = [1, 2, 3, 4, 5];
const add = (a, b) =› a + b;
let sum = arr.reduce(add);
//sum = 15 相当于累加的效果与之相对应的还有一个 ####Array.reduceRight() 方法,区别是这个是从右向左操作的
Array.push()
- 在数组的后面添加新加元素,此方法改变了数组的长度:
Array.pop()
- 在数组后面删除最后一个元素,并返回数组,此方法改变了数组的长度:
let arr = [1, 2, 3, 4, 5];
arr.pop();
console.log(arr); //[1, 2, 3, 4]
console.log(arr.length); //4
Array.shift()
- 在数组后面删除第一个元素,并返回数组,此方法改变了数组的长度:
let arr = [1, 2, 3, 4, 5];
arr.shift();
console.log(arr); //[2, 3, 4, 5]
console.log(arr.length); //4
Array.unshift()
- 将一个或多个元素添加到数组的开头,并返回新数组的长度:
let arr = [1, 2, 3, 4, 5];
arr.unshift(6, 7);
console.log(arr); //[6, 7, 2, 3, 4, 5]
console.log(arr.length); //7
Array.isArray()
- 判断一个对象是不是数组,返回的是布尔值
Array.concat()
- 将多个数组拼接成一个数组:
let arr1 = [1, 2, 3]
arr2 = [4, 5]
let arr = arr1.concat(arr2)
console.log(arr)//[1, 2, 3, 4, 5]
Array.toString()
- 将数组转化为字符串:
let arr = [1, 2, 3, 4, 5];
let str = arr.toString()
console.log(str)// 1,2,3,4,5
Array.join()
- 将数组转化为字符串:
let arr = [1, 2, 3, 4, 5];
let str1 = arr.toString()
let str2 = arr.toString(',')
let str3 = arr.toString('##')
console.log(str1)// 12345
console.log(str2)// 1,2,3,4,5
console.log(str3)// 1##2##3##4##5
Array.splice(开始位置, 删除的个数,元素)
- 万能方法,可以实现增删改:
let arr = [1, 2, 3, 4, 5];
let arr1 = arr.splice(2, 0 'haha')
let arr2 = arr.splice(2, 3)
let arr1 = arr.splice(2, 1 'haha')
console.log(arr1) //[1, 2, 'haha', 3, 4, 5]新增一个元素
console.log(arr2) //[1, 2] 删除三个元素
console.log(arr3) //[1, 2, 'haha', 4, 5] 替换一个元素
16.字符串常用操作
charAt(index)
:返回指定索引处的字符串charCodeAt(index)
:返回指定索引处的字符的Unicode
的值concat(str1,str2,...)
:连接多个字符串,返回连接后的字符串的副本fromCharCode()
:将 Unicode 值转换成实际的字符串indexOf(str)
:返回str
在父串中第一次出现的位置,若没有则返回-1
lastIndexOf(str)
:返回 str 在父串中最后一次出现的位置,若没有则返回-1
match(regex)
:搜索字符串,并返回正则表达式的所有匹配
replace(str1,str2)
:str1
也可以为正则表达式,用str2
替换str1
search(regex)
:基于正则表达式搜索字符串,并返回第一个匹配的位置slice(start,end)
:返回字符索引在start
和end
(不含)之间的子串split(sep,limit)
:将字符串分割为字符数组,limit
为从头开始执行分割的最大数量substr(start,length)
:从字符索引start
的位置开始,返回长度为length
的子串substring(from,to)
:返回字符索引在from
和to
(不含)之间的子串toLowerCase()
:将字符串转换为小写toUpperCase()
:将字符串转换为大写valueOf()
:返回原始字符串值
17.作用域的概念及作用
作用域 :
起作用
的一块区域
作用域的概念: 对
变量
起保护作用
的一块区域作用:
作用域外部
无法获取到作用域内部
声明的变量,作用域内部
能够获取到作用域外界
声明的变量。
18.作用域的分类
块作用域、词法作用域、动态作用域
1). 块作用域
- 花括号 {}
2). 词法作用域
- 作用域只跟在
何处被创建
有关系,跟在何处被调用
没有关系
3). 动态作用域
- 作用域只跟在
何处被调
用有关系,跟在何处被创建
没有关系
19.js 属于哪种作用域
词法作用域(函数作用域)
块作用域
{
var num =123;
}
console.log(num);
如果
js
属于块作用域,那么在花括号外部就无法访问到花括号内部的声明的num变量
。如果
js
不属于块级作用域,那么花括号外部就能够访问到花括号内部声明的num变量
能够输出
num变量
,也就说明js
不属于块级作用。在
ES6
之前的版本js
是不存在块级作用域的。js
属于词法作用域还是动态作用域js
中函数可以帮我们去形成一个作用域
function fn(){
var num =123;
}
fn();
//在函数外界能否访问到num这样一个变量
console.log(num)
//Uncaught ReferenceError: num is not defined
如果
函数
能够生成一个作用域
,那么在函数
外界就无法访问到函数
内部声明的变量。js中的
函数
能够生成一个函数作用域
。
词法作用域
- 作用的外界只跟
作用域
在何处创建有关系,跟作用域
在何处被调用没有关系
var num = 123;
function f1() {
console.log(num); //
}
function f2() {
var num = 456;
f1(); //f1在f2被调用的时候会被执行 。
}
f2();
如果
js
是词法作用域
,那么就会输出f1被创建
的时候外部
的num变量 123如果
js
是动态作用域
,那么f1执行的时候就会输出f1被调用时外部
环境中的num 456
20.自执行函数?用于什么场景?好处?
自执行函数:
1). 声明一个匿名函数
2). 马上调用这个匿名函数。
作用:创建一个
独立
的作用域。好处:防止变量弥散
到全局,以免各种 js 库冲突。隔离作用域避免污染,或者截断作用域链,避免闭包造成引用变量无法释放
。利用立即执行
特性,返回需要的业务函数
或对象
,避免每次通过条件
判断来处理场景:一般用于框架
、插件
等场景
21.多个页面之间如何进行通信
- 有如下几个方式:
cookie
web worker
localeStorage
sessionStorage
22.css 动画和 js 动画的差异
代码复杂度,
js
动画代码相对复杂一些动画运行时,对动画的控制程度上,
js
能够让动画暂停
,取消
,终止
,css
动画不能添加事件动画性能看,
js
动画多了一个js
解析的过程,性能不如css
动画好
23.数组方法 pop() push() unshift() shift()
arr.pop()
从后面删除
元素,只能是一个
,返回值是删除的元素arr.push()
从后面添加
元素,返回值为添加完后的数组的长度arr.unshift()
从前面添加
元素, 返回值是添加完后的数组的长度arr.shift()
从前面删除
元素,只能删除一个
返回值是删除的元素
24.事件绑定与普通事件有什么区别
用
普通事件
添加相同事件,下面会覆盖上面的,而事件绑定
不会普通事件
是针对非 dom
元素,事件绑定
是针对dom元素
的事件
25.IE 和标准下有哪些兼容性的写法
var ev = ev || window.event;
document.documentElement.clientWidth || document.body.clientWidth;
var target = ev.srcElement || ev.target;
26.js 中 this 闭包 作用域
-
this
:指向调用上下文
- 闭包:定义一个函数就开辟了一个
局部作用域
,整个js
执行环境有一个全局作用域
- 作用域:
一个函数
可以访问其他函数中
的变量(闭包是一个受保护的变量空间)
var f = (function fn() {
var name = 1;
return function () {
name++;
console.log(name)
}
})()
==›undefined
27.javascript 的本地对象,内置对象和宿主对象
本地对象
ECMA-262
把本地对象(native object)定义为“独立于宿主环境的ECMAScript
实现提供的对象",简单来说,本地对象
就是ECMA-262
定义的类(引用类型)
- 包括:
Object
、Function
、Array
、String
、Boolean
、Number
、Date
、RegExp
、Error
、EvalError
、RangeError
、ReferenceError
、SyntaxError
、TypeError
、URIError
内置对象
JS
中内置了17
个对象,常用的是Array对象
、Date对象
、正则表达式对象
、string对象
、Global对象
宿主对象
由ECMAScript
实现的宿主环境提供的对象,可以理解为:浏览器提供的对象
,所有的BOM
和DOM
都是宿主对象。
28.javascript 的同源策略
一段脚本只能读取来自于同一来源
的窗口和文档的属性解析:同源策略
:限制从一个源加载
的文档或脚本如何与来自另一个源
的资源进行交互。这是一个用于隔离潜在恶意文件
的关键的安全机制
。(来自 MDN 官方的解释)简单来说就是:一段脚本只能读取来自于同一来源的窗口
和文档
的属性,这里的同一来源指的是主机名
、协议
和端口号
的组合
具体解释:
1). 源包括三个部分:协议
、域名
、端口
(http 协议的默认端口是 80)。如果有任何一个部分不同,则源不同,那就是跨域了
2). 限制:这个源的文档没有权利
去操作另一个源的文档。这个限制体现在:
-
Cookie
、LocalStorage
和IndexDB
无法获取。 - 无法获取和操作
DOM
- 不能发送
ajax
请求(ajax 在不同域名下的请求无法实现,需要进行跨域操作)
29.事件冒泡与事件捕获
- 事件冒泡:由
最具体
的元素(目标元素)向外传播到最不具体
的元素 - 事件捕获:由
最不确定
的元素到目标元素
30.复杂数据类型如何转变为字符串
首先,会调用 valueOf
方法,如果方法的返回值是一个基本数据类型
,就返回这个值
如果调用 valueOf
方法之后的返回值仍旧是一个复杂数据类型
,就会调用该对象的 toString
方法
如果 toString
方法调用之后的返回值是一个基本数据类型
,就返回这个值,
如果 toString
方法调用之后的返回值是一个复杂数据类型
,就报一个错误