1. document load 和 document ready 的区别
答案:页面加载完成有两种事件
1.load是当页面所有资源全部加载完成后(包括DOM文档树,css文件,js文件,图片资源等),执行一个函数
问题:如果图片资源较多,加载时间较长,onload后等待执行的函数需要等待较长时间,所以一些效果可能受到影响
2.$(document).ready()是当DOM文档树加载完成后执行一个函数 (不包含图片,css等)所以会比load较快执行
在原生的js中不包括ready()这个方法,只有load方法也就是onload事件
2.JavaScript 中如何检测一个变量是一个 String 类型?
答案:三种方法(typeof、constructor、Object. prototype. toString. call())
3. 请用 js 去除字符串空格?
方法一:replace 正则匹配方法
去除字符串内所有的空格:str = str. replace(/\s*/g, “”);
去除字符串内两头的空格:str = str. replace(/^\s*|\s*KaTeX parse error: Undefined control sequence: \s at position 43: …str. replace(/^\̲s̲*/, ""); 去除字符串内…)/g, “”);
方法二:str. trim()方法
trim()方法是用来删除字符串两端的空白字符并返回,trim 方法并不影响原来的字符串本身,它返回的是一个新的字符串。
缺陷:只能去除字符串两端的空格,不能去除中间的空格
方法三:JQ 方法:$. trim(str)方法
.
t
r
i
m
(
)
函
数
用
于
去
除
字
符
串
两
端
的
空
白
字
符
。
注
意
:
. trim() 函数用于去除字符串两端的空白字符。 注意:
.trim()函数用于去除字符串两端的空白字符。注意:. trim()函数会移除字符串开始和末尾处的所有换行符,空格(包括连续的空格)和制表符。如果这些空白字符在字符串中间时,它们将被保留,不会被移除。
4. js 是一门怎样的语言,它有什么特点
答案:1. 脚本语言。JavaScript 是一种解释型的脚本语言, C、C++等语言先编译后执行, 而 JavaScript 是在程序的运行过程中逐行进行解释。
2. 基于对象。JavaScript 是一种基于对象的脚本语言, 它不仅可以创建对象, 也能使用现有的对象。
3. 简单。JavaScript 语言中采用的是弱类型的变量类型, 对使用的数据类型未做出严格的要求, 是基于 Java 基本语句和控制的脚本语言, 其设计简单紧凑。
4. 动态性。JavaScript 是一种采用事件驱动的脚本语言, 它不需要经过 Web 服务器就可以对用户的输入做出响应。
5. 跨平台性。JavaScript 脚本语言不依赖于操作系统, 仅需要浏览器的支持。
5. == 和 === 的不同
答案: == 是抽象相等运算符,而 === 是严格相等运算符。 == 运算符是在进行必要的类型转换后,再比较。 === 运算符不会进行类型转换,所以如果两个值不是相同的类型,会直接返回 false 。使用 == 时,可能发生一些特别的事情,例如:
1 == "1"; // true
1 == [1]; // true
1 == true; // true
0 == ""; // true
0 == "0"; // true
0 == false; // true
6. 怎样添加、移除、移动、复制、创建和查找节点?
答案:
1)创建新节点
createDocumentFragment() //创建一个 DOM 片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
2)添加、移除、替换、插入
appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入
3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的 Name 属性的值
getElementById() //通过元素 Id,唯一性
7. 事件委托是什么
答案:利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!
解析:
1、那什么样的事件可以用事件委托,什么样的事件不可以用呢?
- 适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。
- 值得注意的是,mouseover 和 mouseout 虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。
- 不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说 focus,blur 之类的,本身就没用冒泡的特性,自然就不用事件委托了。
2、事件冒泡与事件委托的对比
-
事件冒泡:box 内部无论是什么元素,点击后都会触发 box 的点击事件
-
事件委托:可以对 box 内部的元素进行筛选
-
键盘事件:keydown keypress keyup
-
鼠标事件:mousedown mouseup mousemove mouseout mouseover
8. require 与 import 的区别
答案:两者的加载方式不同、规范不同
第一、两者的加载方式不同,require 是在运行时加载,而 import 是在编译时加载
第二、规范不同,require 是 CommonJS/AMD 规范,import 是 ESMAScript6+规范
第三、require 特点:社区方案,提供了服务器/浏览器的模块加载方案。非语言层面的标准。只能在运行时确定模块的依赖关系及输入/输出的变量,无法进行静态优化。
import 特点:语言规格层面支持模块功能。支持编译时静态分析,便于 JS 引入宏和类型检验。动态绑定。
9. javascript 对象的几种创建方式
答案:第一种:Object 构造函数创建
var Person = new Object();
Person.name = "Nike";
Person.age = 29;
第二种:使用对象字面量表示法
var Person = {}; //相当于 var Person = new Object();
var Person = {
name: 'Nike';
age: 29;
}
第三种:使用工厂模式创建对象
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
alert(this.name);
};
return o;
}
var person1 = createPerson("Nike", 29, "teacher");
var person2 = createPerson("Arvin", 20, "student");
第四种: 使用构造函数创建对象
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
alert(this.name);
};
}
var person1 = new Person("Nike", 29, "teacher");
var person2 = new Person("Arvin", 20, "student");
第五种:原型创建对象模式
function Person() {}
Person.prototype.name = "Nike";
Person.prototype.age = 20;
Person.prototype.jbo = "teacher";
Person.prototype.sayName = function() {
alert(this.name);
};
var person1 = new Person();
person1.sayName();
10. JavaScript 继承的方式和优缺点
答案:六种方式
一、原型链继承
缺点
1、引用类型的属性被所有实例共享
2、在创建 Child 的实例时,不能向 Parent 传参
二、借用构造函数(经典继承)
优点:
避免了引用类型的属性被所有实例共享
可以在 Child 中向 Parent 传参
缺点:
方法都在构造函数中定义,每次创建实例都会创建一遍方法。
三、组合继承
优点:
融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。
四、原型式继承
缺点:
包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。
五、寄生式继承
缺点:
跟借用构造函数模式一样,每次创建对象都会创建一遍方法。
六、寄生组合式继承
优点:
这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent. prototype 上面创建不必要的、多余的属性。
与此同时,原型链还能保持不变;
因此,还能够正常使用 instanceof 和 isPrototypeOf。
开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式
11. 什么是原型链?
答案:通过一个对象的__proto__可以找到它的原型对象,原型对象也是一个对象,就可以通过原型对象的__proto__,最后找到了我们的 Object. prototype, 从实例的原型对象开始一直到 Object. prototype 就是我们的原型链
12. 复杂数据类型如何转变为字符串
答案:
- 首先,会调用 valueOf 方法,如果方法的返回值是一个基本数据类型,就返回这个值,
- 如果调用 valueOf 方法之后的返回值仍旧是一个复杂数据类型,就会调用该对象的 toString 方法,
- 如果 toString 方法调用之后的返回值是一个基本数据类型,就返回这个值,
- 如果 toString 方法调用之后的返回值是一个复杂数据类型,就报一个错误。
13. javascript 的 typeof 返回哪些数据类型
答案:7 种分别为 string、boolean、number、Object、Function、undefined、symbol(ES6)
14. 一次js请求一般情况下有哪些地方会有缓存处理?
答案:DNS缓存,CDN缓存,浏览器缓存,服务器缓存。
15. 列举 3 种强制类型转换和 2 种隐式类型转换
答案:强制: parseInt(), parseFloat(), Number(), Boolean(), String() 隐式: +, -
16. 你对闭包的理解?优缺点
答案:概念:闭包就是能够读取其他函数内部变量的函数。
三大特性:
1.函数嵌套函数。
2.函数内部可以引用外部的参数和变量。
3.参数和变量不会被垃圾回收机制回收。
优点:
1.希望一个变量长期存储在内存中。
2.避免全局变量的污染。
3.私有成员的存在。
缺点:
常驻内存,增加内存使用量。
使用不当会很容易造成内存泄露。
17. 如何判断 NaN
答案:isNaN()方法
18. new 一个对象的过程中发生了什么
- 创建空对象;
- 设置原型链: 设置新对象的 constructor 属性为构造函数的名称,设置新对象的__proto__属性指向构造函数的 prototype 对象;
- 改变this指向:使用新对象调用函数,函数中的 this 指向新实例对象obj:
- 返回值:如果无返回值或者返回一个非对象值,则将新对象返回;如果返回值是一个新对象的话那么直接返回该对象。
19. for in 和 for of的区别
答案:
1、for in
- 一般用于遍历对象的可枚举属性。以及对象从构造函数原型中继承的属性。对于每个不同的属性,语句都会被执行。
- 不建议使用 for in 遍历数组,因为输出的顺序是不固定的。
- 如果迭代的对象的变量值是 null 或者 undefined, for in 不执行循环体,建议在使用 for in 循环之前,先检查该对象的值是不是 null 或者 undefined。
2、for of
- for…of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
20. 如何判断 JS 变量的一个类型(至少三种方式)
答案:typeof、instanceof、 constructor、 prototype
21. for in、Object. keys 和 Object. getOwnPropertyNames 对属性遍历有什么区别?
答案:
- for in 会遍历自身及原型链上的可枚举属性
- Object. keys 会将对象自身的可枚举属性的 key 输出
- Object. getOwnPropertyNames会将自身所有的属性的 key 输出
22. 如何判断一个对象是否为数组
答案:
第一种方法:使用 instanceof 操作符。
第二种方法:使用 ECMAScript 5 新增的 Array. isArray()方法。
第三种方法:使用使用 Object. prototype 上的原生 toString()方法判断。
23.script标签的 defer 和 asnyc 属性的作用以及二者的区别?
答案:
1、defer 和 async 的网络加载过程是一致的,都是异步执行。
2、区别在于加载完成之后什么时候执行,可以看出 defer 是文档所有元素解析完成之后才执行的。
3、如果存在多个 defer 脚本,那么它们是按照顺序执行脚本的,而 async,无论声明顺序如何,只要加载完成就立刻执行
24. Object. prototype. toString. call() 和 instanceOf 和 Array. isArray() 区别好坏
答案:
- Object. prototype. toString. call()
优点:这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined 。
缺点:不能精准判断自定义对象,对于自定义对象只会返回[object Object] - instanceOf
优点:instanceof 可以弥补 Object. prototype. toString. call()不能判断自定义实例化对象的缺点。
缺点: instanceof 只能用来判断对象类型,原始类型不可以。并且所有对象类型 instanceof Object 都是 true,且不同于其他两种方法的是它不能检测出 iframes。 - Array. isArray()
优点:当检测 Array 实例时,Array. isArray 优于 instanceof ,因为 Array. isArray 可以检测出 iframes
缺点:只能判别数组
25. 什么是面向对象?
答案:面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。
26. 你对松散类型的理解
答案:
JavaScript 中的变量为松散类型,所谓松散类型就是指当一个变量被申明出来就可以保存任意类型的值,就是不像 SQL 一样申明某个键值为 int 就只能保存整型数值,申明 varchar 只能保存字符串。一个变量所保存值的类型也可以改变,这在 JavaScript 中是完全有效的,只是不推荐。相比较于将变量理解为“盒子“,《JavaScript 编程精解》中提到应该将变量理解为“触手”,它不保存值,而是抓取值。这一点在当变量保存引用类型值时更加明显。
JavaScript 中变量可能包含两种不同的数据类型的值:基本类型和引用类型。基本类型是指简单的数据段,而引用类型指那些可能包含多个值的对象。
27. 移动端 click 事件、touch 事件、tap 事件的区别
答案:
-
click 事件在移动端会有 200-300ms ms 的延迟,主要原因是苹果手机在设计时,考虑到用户在浏览网页时需要放大,所以,在用户点击的 200-300ms 之后,才触发 click,如果 200-300ms 之内还有 click,就会进行放大缩小。
-
touch 事件是针对触屏手机上的触摸事件。现今大多数触屏手机 webkit 内核提供了 touch 事件的监听,让开发者可以获取用户触摸屏幕时的一些信息。其中包括:touchstart, touchmove, touchend, touchcancel 这四个事件,touchstart touchmove touchend 事件可以类比于 mousedown mouseover mouseup 的触发
-
tap 事件在移动端,代替 click 作为点击事件,tap 事件被很多框架(如 zepto)封装,来减少这延迟问题, tap 事件不是原生的,所以是封装的
28. JS 单线程还是多线程,如何显示异步操作
答案:JS 本身是单线程的,他是依靠浏览器完成的异步操作。
具体步骤,
1、主线程 执行 js 中所有的代码。
2、主线程 在执行过程中发现了需要异步的任务任务后扔给浏览器(浏览器创建多个线程执行),并在 callback queque 中创建对应的回调函数(回调函数是一个对象,包含该函数是否执行完毕等)。
3、主线程 已经执行完毕所有同步代码。开始监听 callback queque 一旦 浏览器 中某个线程任务完成将会改变回调函数的状态。主线程查看到某个函数的状态为已完成,就会执行该函数。
29. JS 块级作用域、变量提升
答案:
-
块级作用域
JS 中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称 ES6)中新增了块级作用域。块作用域由 { } 包括,if 语句和 for 语句里面的{ }也属于块作用域。 -
变量提升
如果变量声明在函数里面,则将变量声明提升到函数的开头
如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头
30. null/undefined 的区别
答案:
null: Null 类型,代表“空值",代表一个空对象指针,使用 typeof 运算得到 “object",所以你可以认为它是一个特殊的对象值。
undefined: Undefined 类型,当一个声明了一个变量未初始化时,得到的就是 undefined。
31.JS哪些操作会造成内存泄露
1)意外的全局变量引起的内存泄露
2)闭包引起的内存泄露
3)没有清理的 DOM 元素引用
4)被遗忘的定时器或者回调
5)子元素存在引起的内存泄露
6)IE7/8 引用计数使用循环引用产生的问题
32. jsonp 优缺点?
答案:jsonp 优缺点
优点
1 它不像 XMLHttpRequest 对象实现的 Ajax 请求那样受到同源策略的限制,JSONP 可以跨越同源策略;
2 它的兼容性更好,在更加古老的浏览器中都可以运行,不需要 XMLHttpRequest 或 ActiveX 的支持
3 在请求完毕后可以通过调用 callback 的方式回传结果。将回调方法的权限给了调用方。这个就相当于将 controller 层和 view 层终于分 开了。我提供的 jsonp 服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续 view 操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个 jsonp 服务。
缺点
1 它只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求
2 它只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。
3 jsonp 在调用失败的时候不会返回各种 HTTP 状态码。
4 缺点是安全性。万一假如提供 jsonp 的服务存在页面注入漏洞,即它返回的 javascript 的内容被人控制的。那么结果是什么?所有调用这个 jsonp 的网站都会存在漏洞。于是无法把危险控制在一个域名下…所以在使用 jsonp 的时候必须要保证使用的 jsonp 服务必须是安全可信的
33. split() join()的区别
答案:
join():用于把数组中的所有元素通过指定的分隔符进行分隔放入一个字符串
split():用于把一个字符串通过指定的分隔符进行分隔成数组
34. JavaScript的数据类型
答案:JS 数据类型共有六种,分别是 String、Number、Boolean、Null、Undefined 和 Object 等, 另外,ES6 新增了 Symbol 类型。其中,Object 是引用类型,其他的都是基本类型(Primitive Type)。
35.call() 和 apply() 的含义和区别
答案:
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B. call(A, args1, args2); 即 A 对象调用 B 对象的方法。
apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B. apply(A, arguments); 即 A 对象应用 B 对象的方法。
call 与 apply 的相同点:
方法的含义是一样的,即方法功能是一样的;
第一个参数的作用是一样的;
call 与 apply 的不同点:两者传入的列表形式不一样
call 可以传入多个参数;
apply 只能传入两个参数,所以其第二个参数往往是作为数组形式传入
36. sort 排序原理
答案:冒泡排序法
冒泡排序法的原理:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。