1.js有几种数据类型,其中基本数据类型有哪些?
基本类型:Undefined、Null、Boolean、Number、String和Symbol。
引用类型:Object、Array和Function等。
2.js有哪些内置对象?
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error
3.判断 js 类型的方式
1.最常见的判断方法:typeof
可以判断出'string','number','boolean','undefined','symbol',’function’,但判断 typeof(null) 时值 为 'object'; 判断数组和对象时值均为 'object'。
2.判断已知对象类型的方法: instanceof
原理是构造函数的 prototype 属性是否出现在对象的原型链中的任何位置;
3.根据对象的constructor判断:
alert(c.constructor === Array) ----------> true
4.通用但很繁琐的方法: prototype
Object.prototype.toString.call():常用于判断浏览器内置对象,对于所有基本的数据类 型都能进行判断,即使是 null 和 undefined
5.无敌万能的方法:jquery.type()
jQuery.type( undefined ) === "undefined"
4.js的typeof返回有哪些类型
1.String
2.Number
3.Boolean
4.Object
5.Function
6.undefined
5.Javascript中的定时器有哪些?他们的区别及用法是什么?
setTimeout 只执行一次
setInterval 会一直重复执行
6.js字符串操作函数
列举了常用的字符串函数
1.length – 返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。
2.concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串。
3.indexOf() – 返回字符串中一个子串第一处出现的索引。如果没有匹配项,返回 -1 。
4.lastIndexOf() – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。
5.charAt() – 返回指定位置的字符。
6.substr() 函数 -- 返回从string的startPos位置,长度为length的字符串
7.substring() – 返回字符串的一个子串。传入参数是起始位置和结束位置。
8.slice() – 提取字符串的一部分,并返回一个新字符串。
9.split() – 通过将字符串划分成子串,将一个字符串做成一个字符串数组。
10.match() – 检查一个字符串是否匹配一个正则表达式。
11.replace() – 用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。
12.search() – 执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。
13.toLowerCase() – 将整个字符串转成小写字母。
14.toUpperCase() – 将整个字符串转成大写字母。
7.数组的splice方法?
1.删除——可以删除任意数量的项,只需要指定2个参数:要删除的第一项的位置和要删除项的项数。例如,splice(0,2)会删除数组中的前两项。
2.插入——可以向指定位置插入任意数量的项,只需要提供3个参数:插入起始位置、0(要删除的项数)和要插入的项。 如果要插入多个项,可以再传入第四、第五,一直任意多个项。例如,splice(2,0,”red”,”green”)会从位置2开始插入字符串“red”和”green”。
3.替换——即删除和插入数量相等项数的综合应用,可以指向指定位置插入任意数量的项,且同时删除任意数量的项,只需要指定3个指定参数:起始位置、要删除的项数和要插入的任意数量项。 插入的项数是不必与删除的项数相等。例如,splice(2,2,”red”,”green”)会删除当前数组位置2的项,然后再从位置2开始插入字符串“red”和“green”。
splice()方法始终都会返回一个数组,该数组中包含从元素数组中删除的项(如果没有删除任何项,则返回一个空数组)。
8.for...in和for...of的区别?
均可以遍历数组和对象。
简单总结就是,for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值(即value)。for-in总是得到对象的key或数组字符串的下标。for-of总是得到对象的value或数组字符串的值,另外还可以用于遍历Map和Set。
使用for-in遍历数组会存在以下问题:
var arr = [1, 2, 4, 5, 7];
for (var index in arr) {
console.log(myArray[index]);
}
1.index索引为字符串型数字(注意,非数字),不能直接进行几何运算。
2.遍历顺序有可能不是按照实际数组的内部顺序(可能按照随机顺序)。
3.使用for-in会遍历数组所有的可枚举属性,包括原型。例如上例的原型方法method和name属性都会被遍历出来,通常需要配合hasOwnProperty()方法判断某个属性是否该对象的实例属性,来将原型对象从循环中剔除。
for (var key in myObject) {
if(myObject.hasOwnProperty(key)){
console.log(key);
}
}
9.给一个对象添加属性和方法的三种方案**?**
常用的有三种:
1.直接在空对象上面添加;
2.构造函数原型上添加;
3.立即执行函数中定义空对象添加属性和方法后返回。
10.类数组转换为数组的方法
Array.prototype.slice.call(arguments);
Array.from()
11.改变数组长度的方法有哪些?
shift、unshift、pop、push
12.写出最简单的去重方式
1.es6的new Set()方式
[...new Set([1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0])]
2.es5的Array filter()
[1,3,4,5,1,2,3,3,4,8,90,3,0,5,4,0].filter(function(elem,index,Array){
return index === Array.indexOf(elem);
})
13.javascript对象的几种创建方式
1,工厂模式
2,构造函数模式
3,原型模式
4,混合构造函数和原型模式
5,动态原型模式
6,寄生构造函数模式
7,稳妥构造函数模式
14.javascript继承的6种方法
1,原型链继承
2,借用构造函数继承
3,组合继承(原型+借用构造)
4,原型式继承
5,寄生式继承
6,寄生组合式继承
15.ES6中的箭头函数和普通函数有什么区别?
1.普通函数中的this总是指向调用它的那个对象,箭头函数没有自己的this,他的this永远指向其定义环境,任何方法都改变不了其指向,如call()、bind()、apply()。(正是因为它没有this,所以也就不能用作构造函数,也没有原型对象)
2.箭头函数不能当作构造函数,也就是说,不能使用new命令,否则会报错。
3.箭头函数没有原型属性。
4.箭头函数不能使用yield命令,因此箭头函数不能用作genertor函数。
5.箭头函数不能使用argument对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
6.变量提升:由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let、const)关键字,而var所定义的变量不能得到变量提升。故箭头函数一定要定义于调用之前。
16.this对象的理解
1.this总是指向函数的直接调用者(而非间接调用者);
2.如果有new关键字,this指向new出来的那个对象;
3.在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window。
17.call() 和 apply() 的区别和作用?
作用:动态改变某个类的某个方法的运行环境(执行上下文)。
apply()函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。如:function.apply(this,[1,2,3]);
call()的第一个参数是上下文,后续是实例传入的参数序列。如:function.call(this,1,2,3);
18.闭包的概念?优缺点?
闭包的概念:闭包就是能读取其他函数内部变量的函数。
优点:
1.避免全局变量的污染
2.希望一个变量长期存储在内存中(缓存变量)
缺点:
1.内存泄露(消耗)
2.常驻内存,增加内存使用量
19.说说你对Promise的理解
Promise是一个异步编程的解决方案,简单来讲,Promise类似一个盒子,里面保存着在未来某个时间点才会结束的事件。
依照 Promise/A+ 的定义,Promise 有三种状态:
pending:进行中
fulfilled :已经成功
rejected :已经失败
状态改变,只能从 pending 变成 fulfilled 或者 rejected,状态不可逆。
构造一个 Promise,最基本的用法如下:
var promise = new Promise(function(resolve, reject) {
if (...) { // succeed
resolve(result);
} else { // fails
reject(Error(errMessage));
}
});
Promise 实例拥有 then 方法(具有 then 方法的对象,通常被称为 thenable)。它的使用方法如下:
promise.then(onFulfilled, onRejected)
接收两个函数作为参数,一个在 fulfilled 的时候被调用,一个在 rejected 的时候被调用,接收参数就是 future,onFulfilled对应 resolve, onRejected 对应 reject。
20.介绍下 promise.all
Promise.all()方法将多个Promise实例包装成一个Promise对象(p),接受一个数组(p1,p2,p3)作为参数,数组中不一定需要都是Promise对象,但是一定具有Iterator接口,如果不是的话,就会调用Promise.resolve将其转化为Promise对象之后再进行处理。
使用Promise.all()生成的Promise对象(p)的状态是由数组中的Promise对象(p1,p2,p3)决定的。
1.如果所有的Promise对象(p1,p2,p3)都变成fullfilled状态的话,生成的Promise对象(p)也会变成fullfilled状态,p1,p2,p3三个Promise对象产生的结果会组成一个数组返回给传递给p的回调函数。
2.如果p1,p2,p3中有一个Promise对象变为rejected状态的话,p也会变成rejected状态,第一个被rejected的对象的返回值会传递给p的回调函数。Promise.all()方法生成的Promise对象也会有一个catch方法来捕获错误处理,但是如果数组中的Promise对象变成rejected状态时,并且这个对象还定义了catch的方法,那么rejected的对象会执行自己的catch方法。并且返回一个状态为fullfilled的Promise对象,Promise.all()生成的对象会接受这个Promise对象,不会返回rejected状态。
21.promise的优缺点?
优点:解决了回调地狱的问题,将异步操作以同步操作的流程表达出来。
缺点:
1.无法取消promise。
2.如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
3.当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
4.当执行多个Promise时,一堆then看起来也很不友好。
22.异步编程的发展史?
JS的异步发展史,可以认为是从 callback -> promise -> generator -> async/await。async/await 使得异步代码看起来像同步代码,异步编程发展的目标就是让异步逻辑的代码看起来像同步一样。
23.DOM 事件有哪些阶段?谈谈对事件代理的理解
分为三大阶段:
1.一开始从文档的根节点流向目标对象(捕获阶段)
2.然后在目标对向上被触发(目标阶段)
3.之后再回溯到文档的根节点(冒泡阶段)。
事件代理简单说就是:事件不直接绑定到某元素上,而是绑定到该元素的父元素上,进行触发事件操作时(例如'click'),再通过条件判断,执行事件触发后的语句(例如'alert(e.target.innerHTML)')
好处:(1)使代码更简洁;(2)节省内存开销
24.DOM怎样添加、移除、替换、插入、创建和查找节点
1.创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2.添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点
3.查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
25.null和undefined的区别?
null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
undefined:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
null:
(1)作为函数的参数,表示该函数的参数不是对象。
(2)作为对象原型链的终点。
26.字符串和数字的相互转换?
1.数字 --> 字符串
value.toString()、 "" + value、String(value)
2.字符串 --> 数字
+value、Number(value)、parseInt(string, radix)、 parseFloat(value)
27.new操作符具体干了什么呢?
(1)创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
(2)属性和方法被加入到 this 引用的对象中。
(3)新创建的对象由 this 所引用,并且最后隐式的返回 this 。
28.JSON 的了解?
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于JavaScript的一个子集。数据格式简单, 易于读写, 占用带宽小。
格式:采用键值对,例如:{'age':'12', 'name':'back'}
29.eval是做什么的?
它的功能是把对应的字符串解析成JS代码并运行;
应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)。
由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')')。
30.浅拷贝和深拷贝的问题
浅拷贝只是增加了一个指针指向已存在的内存地址;深拷贝是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存。
浅拷贝的方法:
1.Object.assign()
2.扩展运算符(...)
3.Array.prototype.slice()
4.直接赋值=
深拷贝的方法:
1.JSON.stringify()
2.递归
通过JSON.stringify实现深拷贝有几点要注意:
1.拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的 JSON字符串中这个键值对会消失
2.无法拷贝不可枚举的属性,无法拷贝对象的原型链
3.拷贝Date引用类型会变成字符串
4.拷贝RegExp引用类型会变成空对象
5.对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
6.无法拷贝对象的循环应用(即obj[key] = obj)
31.请解释一下 JavaScript 的同源策略。
概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议。
指一段脚本只能读取来自同一来源的窗口和文档的属性。
32.为什么要有同源限制?
我们举例说明:比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。
缺点:
现在网站的JS 都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge 后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节。
33.请用js去除字符串空格?
方法一:使用replace正则匹配的方法
去除所有空格: str = str.replace(/\s*/g,"");
去除两头空格: str = str.replace(/^\s|\s$/g,"");
去除左空格: str = str.replace( /^\s*/, "");
去除右空格: str = str.replace(/(\s*$)/g, "");
方法二:使用str.trim()方法
str.trim()局限性:无法去除中间的空格,同理,str.trimLeft(),str.trimRight()分别用于去除字符串左右空格。
方法三:使用jquery,$.trim(str)方法
$.trim(str)局限性:无法去除中间的空格
34.JavaScript中如何检测一个变量是一个String类型?请写出函数实现
typeof(obj) === "string"
typeof obj === "string"
obj.constructor === String
35.使用正则表达式验证邮箱格式
var reg = /^(\w)+(\.\w+)*@(\w)+((\.\w{2,3}){1,3})$/;
var email = "example@qq.com";
console.log(reg.test(email)); // true
36.简述**同步和异步的区别**
同步是阻塞模式,异步是非阻塞模式。
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。