window.onload和$(document).ready()的区别:
window.onload是在页面中包含图片在内的所有元素全部加载完成在执行;
$(document).ready()是DOM树加载完成之后执行,不包含图片,其他媒体文件;
因此$(document).ready()快于window.onload执行
javascript的typeof返回哪些数据类型
Object number function boolean underfind string
例举3种强制类型转换和2种隐式类型转换
强制(parseInt,parseFloat,number)
隐式(== - ===)
split() join() 的区别
前者是切割成数组的形式,后者是将数组转换成字符串
IE和DOM事件流的区别
1.执行顺序不一样、
2.参数不一样
3.事件加不加on
4.this指向问题
IE和标准下有哪些兼容性的写法
Var ev = ev ||window.event
document.documentElement.clientWidth ||document.body.clientWidth
Var target = ev.srcElement||ev.target
ajax请求的时候get 和post方式的区别
1.一个在url后面 一个放在虚拟载体里面
2.有大小限制
3.安全问题
4.应用不同 一个是论坛等只需要请求的,一个是类似修改密码的
ajax请求时,如何解析json数据
使用eval parse 鉴于安全性考虑使用parse更靠谱
写一个获取非行间样式的函数
function getStyle(obj, attr, value) {
if(!
value) {
if(obj.currentStyle) {
return obj.currentStyle(attr)
}
else {
obj.getComputedStyle(attr,
false)
}
}
else {
obj.style[attr]=
value
}
}
如何阻止事件冒泡和默认事件
stoppropagation / preventdefault
排序算法
升序:
varnumberArray = [
3,
6,
2,
4,
1,
5];
numberArray.sort(
function(a,b){
return a-b;
})
console.log(numberArray);
冒泡排序
var examplearr=[
8,
94,
15,
88,
55,
76,
21,
39];
function sortarr(arr){
for(i=
0;i<arr.length
-1;i++){
for(j=
0;j<arr.length
-1-i;j++){
if(arr[j]>arr[j+
1]){
var temp=arr[j];
arr[j]=arr[j+
1];
arr[j+
1]=temp;
}
}
}
return arr;
}
sortarr(examplearr);
console.log(examplearr);
null和undefined的区别:
null:表示无值;undefined:表示一个未声明的变量,或已声明但没有赋值的变量,
或一个并不存在的对象属性。
请解释变量声明提升。
在函数执行时,把变量的声明提升到了函数顶部,而其值定义依然在原来位置。
如何从浏览器的URL中获取查询字符串参数
以下函数把获取一个key的参数。
function parseQueryString ( name )
{
name = name.replace(
/[\[]/,
"\\\[");
var
regexS =
"[\\?&]"+name+
"=([^&#]*)";
var
regex =
newRegExp
( regexS );
var
results = regex.exec(
window.location.href );
if
(results ==
null) {
return
""
;
}
else{
return
results[
1];
}
}
arguments是什么
arguments虽然有一些数组的性质,但其并非真正的数组,只是一个类数组对象。
其并没有数组的很多方法,不能像真正的数组那样调用.jion(),.concat(),.pop()等方法。
什么是回调函数?
1.就是一个函数的调用过程。那么就从理解这个调用过程开始吧。
函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。
2.另外种解释:开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。
通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。
使用 typeof bar === “object” 判断 bar 是不是一个对象有神马潜在的弊端?如何避免这种弊端?
let obj = {};
let arr = [];
console.log(
typeofobj ===
'object');
//true
console.log(
typeofarr ===
'object');
//true
从上面的输出结果可知,typeof bar === “object” 并不能准确判断 bar 就是一个 Object。可以通过Object.prototype.toString.call(bar) === “[object Object]” 来避免这种弊端:
let obj = {};
let arr = [];
console.
log(Object.prototype.toString.
call(obj));
//[object Object]
console.
log(Object.prototype.toString.
call(arr));
//[object Array]
谈谈你对Ajax的理解?(概念、特点、作用)
AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML)是指一种创建交互式网页应用的开发技术、改善用户体验,实现无刷新效果。
优点
a、不需要插件支持
b、优秀的用户体验
c、提高Web程序的性能
d、减轻服务器和带宽的负担
缺点
a、破坏浏览器“前进”、“后退”按钮的正常功能,可以通过简单的插件弥补
b、对搜索引擎的支持不足
说说你对延迟对象deferred的理解?
a、什么是deferred对象
在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是”延迟”,所以deferred对象的含义就是”延迟”到未来某个点再执行。
它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。
b、它的主要功能,可以归结为四点:
(1)、实现链式操作
(2)、指定同一操作的多个回调函数
(3)、为多个操作指定回调函数
(4)、普通操作的回调函数接口
JavaScript的数据类型有哪些?
基本数据类型:字符串 String、数字 Number、布尔Boolean
复合数据类型:数组 Array、对象 Object
特殊数据类型:Null 空对象、Undefined 未定义
根据你的理解,请简述JavaScript脚本的执行原理?
JavaScript是一种动态、弱类型、基于原型的语言,通过浏览器可以直接执行。
当浏览器遇到<script> 标记的时候,浏览器会执行之间的javascript代码。嵌入的js代码是顺序执行的,每个脚本定义的全局变量和函数,都可以被后面执行的脚本所调用。 变量的调用,必须是前面已经声明,否则获取的变量值是undefined。
ionic和angularjs的区别?
a.ionic是一个用来开发混合手机应用的,开源的,免费的代码库。可以优化html、css和js的性能,构建高效的应用程序,而且还可以用于构建Sass和AngularJS的优化。
b、AngularJS通过新的属性和表达式扩展了HTML。AngularJS可以构建一个单一页面应用程序(SPAs:Single Page Applications)。
c、Ionic是一个混合APP开发工具,它以AngularJS为中间脚本工具(称为库,似乎又不恰当),所以,你如果要使用Ionic开发APP,就必须了解AngularJS。
JavaScript对象的几种创建方式?
(1) 工厂模式
function Parent(){
varChild =
newObject
();
Child.name=
"欲泪成雪";
Child.age=
"20";
return Child;
};
var x = Parent();
引用该对象的时候,这里使用的是 var x = Parent()而不是 var x = new Parent();因为后者会可能出现很多问题(前者也成为工厂经典方式,后者称之为混合工厂方式),不推荐使用new的方式使用该对象
(2)构造函数方式
function Parent(){
this
.name=
"欲泪成雪";
this
.age=
"20";
};
varx =
newParent();
(3) 原型模式
function Parent(){
};
Parent.prototype.name=
"欲泪成雪";
Parent.prototype.age=
"20";
varx =
newParent
();
(4)混合的构造函数,原型方式(推荐)
function Parent(){
this
.name=
"欲泪成雪";
this
.age=
22;
};
Parent.prototype.lev=
function(){
return
this
.name;
};
varx =
newParent();
(5)动态原型方式
function Parent(){
this
.name=
"欲泪成雪";
this
.age=
22;
;
if(
typeofParent._lev==
"undefined"){
Parent.prototype.lev=
function(){
return
this
.name;
}
Parent._lev=
true;
}
};
varx =
newParent();
请写出js内存泄漏的问题?
回答一:
(1)、IE7/8 DOM循环引用导致内存泄漏
a、多个对象循环引用
b、循环引用自己
(2)、基础的DOM泄漏
当原有的DOM被移除时,子结点引用没有被移除则无法回收。
(3)、timer定时器泄漏
这个时候你无法回收buggyObject,解决办法,先停止timer然后再回收
回答二:
内存泄漏指任何对象在您不再拥有或需要它之后仍然存在。
垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收。
setTimeout的第一个参数使用字符串而非函数的话,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)也会引发内存泄漏问题。
请你解释一下事件冒泡机制
a、在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。
b、冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发
c、js冒泡机制是指如果某元素定义了事件A,如click事件,如果触发了事件之后,没有阻止冒泡事件,那么事件将向父级元素传播,触发父类的click函数。
//阻止冒泡时间方法,兼容ie(e.cancleBubble)和ff(e.stopProgation)
function stopBubble(e){
varevt = e||
window.event;
evt.stopPropagation?evt.stopPropagation():(evt.cancelBubble=
true);
//阻止冒泡
evt.preventDefault
说说你对Promise的理解?
ES6 原生提供了 Promise 对象。
promise是一种封装未来值的易于复用的异步任务管理机制,主要解决地狱回调和控制异步的顺序
所谓 Promise,就是一个对象,用来传递异步操作的消息。它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的 API,可供进一步处理。
Promise 对象有以下两个特点:
(1)、对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是「承诺」,表示其他手段无法改变。
(2)、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。
Promise 也有一些缺点。首先,无法取消 Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于 Pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
1.应用方法一
exportconst promiseDemo=
()=>{
newPromise(
(resolve,reject)=>{
resolve(
()=>{
let a=
1;
return
++a;
}).
then(
(data)=>{
console
.log(data)
//data
值为++a的值
}).
catch(
()=>{
//错误执行这个
})
})
}
2.应用方法二
exportconst
promiseDemo=
()=>{
Promise.resolve([
1,
2,
3]).then(
(data)=>{
//直接初始化一个Promise并执行resolve方法
console
.log(data)
//data值为[1,2,3]
})
}
如何禁用网页菜单右键?
<script>
function Click(){
window.event.returnValue=false;
}
document.οncοntextmenu=Click;
</script>
恢复方法:javascript:alert(document.oncontextmenu='')
JS应该放在什么位置?
(1)、放在底部,虽然放在底部照样会阻塞所有呈现,但不会阻塞资源下载。
(2)、如果嵌入JS放在head中,请把嵌入JS放在CSS头部。
(3)、使用defer(只支持IE)
(4)、不要在嵌入的JS中调用运行时间较长的函数,如果一定要用,可以用setTimeout来调用
数组去重
const arr = ['a', 'bb', '11', 'a','haha', '22'];
方法一: es6数据结构 Set
let unique = new Set(arr)
console.log(Array.form(unique))
方法二:使用push()
let arr2 = [];
for(let i =0; i < arr.length; i++) {
if(arr2.indexOf(arr[i]) == -1) { //不包含某个值则返回-1
arr2.push(arr[i]);
}
}
console.log(arr2);
//如果当前数组的第i项在当前数组中第一次出现的位置不是i,那么表示第i项是重复的,忽略掉。否则存入结果数组
let arr3 = [arr[0]];
for(let i =1; i < arr.length; i++) {
if(arr.indexOf(arr[i]) == i) {
arr3.push(arr[i]);
}
}
console.log(arr3);
方法三.排序去除相邻重复元素
let arrSort = arr.sort();
let arr4 = [];
for(let i = 0; i< arrSort.length; i++) {
if(arrSort[i] != arrSort[i+1]) {
arr4.push(arrSort[i]);
}
}
console.log(arr4);
方法四:使用splice()
let len = arr.length;
for(let i =0; i < len; i++) {
for(let j = i + 1;j < len; j++) {
if(arr[i] === arr[j]) {
arr.splice(i,1);
len--;
j--;
}
}
}
console.log(arr);
事件委托
让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!
var oUl = document.getElementById('oul');
oUl.addEventListener('click', function(e){
var e = e||window.event;
var tar = e.target;
if(tar.nodeName === 'LI') {
alert(tar.innerHTML);
}
})
判断变量类型
- typeof()用于判断简单数据:判断字符串得到string,数字和NaN得到number,函数会得到function等,但是判断数组,对象和null时都会得到object,这就是typeof的局限性,并不能准确的判断该变量的"真实身份"。
· instanceof: instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性,意思就是该变量通过原型链上能否找到构造函数的prototype属性。使用instanceof可以用来判断一个变量是数组还是对象,原理如下:数组也是对象的一种,使用instanceof都会返回true
var arr = new Array();
var arr = ['aa','bb','cc'];
var obj = {
a: 'aa',
b: 'bb',
c: 'cc'
}
console.log(arr instanceof Array); //true
console.log(arr instanceof Object); //true
console.log(obj instanceof Array); //false
console.log(obj instanceof Object); //true
所以就能明白为什么instanceof判断一个变量可以分清楚它到底是数组还是对象
Array.prototype === arr.__proto__
Object.prototype === arr.__proto__.__proto__
因为arr的原型链上存在Array.prototype和Object.prototype
只有Array类型的变量才会满足arr instanceof Array和arr instanceof Object都返回true,
也只有Object类型变量才满足obj instanceof Array返回false,obj instanceof Object返回true
· constructor
var arr = ['aa','bb','cc'];
var obj = {
a: 'aa',
b: 'bb',
c: 'cc'
}
console.log(arr.constructor === Array); //true
console.log(arr.constructor === Object); //false
console.log(obj.constructor === Object); //true
· Object.prototype.toString.call()
Object.prototype.toString.call()方法可以精准判断变量类型,它返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名
var a = NaN;
var b= '222';
var c = null;
var d = false;
var e = undefined;
var f = Symbol();
var arr = ['aa','bb','cc'];
var obj = {
a: 'aa',
b: 'bb',
c: 'cc'
}
var res = Object.prototype.toString.call(arr);
console.log(res); //[object Array]
var res2 = Object.prototype.toString.call(obj);
console.log(res2); //[object Object]
var res3 = Object.prototype.toString.call(a);
console.log(res3); //[object Number]
var res4 = Object.prototype.toString.call(b);
console.log(res4); //[object String]
var res4 = Object.prototype.toString.call(c);
console.log(res4); //[object Null]
var res5 = Object.prototype.toString.call(d);
console.log(res5); //[object Boolean]
var res6 = Object.prototype.toString.call(e);
console.log(res6); //[object Undefined]
var res7 = Object.prototype.toString.call(f);
console.log(res7); //[object Symbol]
总结:判断简单数据类型可以用typeof,判断数组,对象使用instanceof,constructor和 Object.prototype.toString.call(),最好使用Object.prototype.toString.call(),更加精准
同步和异步
同步:由于js单线程,同步任务都在主线程上排队执行,前面任务没执行完成,后面的任务会一直等待;
异步:不进入主线程,进入任务队列,等待主线程任务执行完成,开始执行。最基础的异步操作setTimeout和setInterval,等待主线程任务执行完,在开始执行里面的函数;
详情点击:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
返回false的几种情况
false,null,0, '0', +0, -0,,“”,undefined,NaN
要注意空数组([])和空对象({}):
console.log([] ==
false)
//true
console
.log({} ==
false)
//false
console
.log(
Boolean([]))
//true
js类型值的区别
存储地:
简单数据类型:存储在栈中;
引用数据类型:存储在堆中,在栈中存储了指针,指向存储在堆中的地址,解释器会先检索在栈中的地址,从堆中获得实体;
大小:
简单数据类型:大小固定,占用空间小,频繁使用,所以存储在栈中;
引用数据类型:大小不固定,占用空间大;
闭包
何为闭包:有权访问另一个作用域中变量的函数
闭包特性:可实现函数外访问函数内变量,外层变量可以不被垃圾回收机制回收
为什么?怎么解决?
for(var i =0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
输出结果都为10,因为for()循环过程中每次传值,匿名函数并没有执行,相当于执行10次function(){console.log(i);},循环结束i变为10,所以输出全部为10;
使用闭包,自执行匿名函数包裹:
for(var i = 0; i < 10; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
外部匿名函数立即执行,把 i 作为参数,赋值给 j ,因为是立即执行,所以每次循环输出不同值。
引用外层变量不被回收,会相比其他函数占用更高内存,使用不当容易造成内存泄漏。
this的指向
全局范围:指向window(严格模式下不存在全局变量,指向undefined);
普通函数调用:指向window;
对象方法调用:指向最后调用它的对象;
构造函数调用:指向new出来的对象;
显示设置this:call,apply方法显示将this指向第一个参数指明的对象
new具体做了些什么
创建一个新对象foo;
并将它的__proto__指向其构造函数的prototype,foo.__proto__ = Foo.prototype;
动态将this指向新对象,Foo.apply(foo,arguments);
执行函数体中的代码;
放回新对象foo;
原型和原型链
创建一个函数就会为其创建一个prototype属性,指向这个函数的原型对象,原型对象会自动获得constructor属性,指向prototype属性所在函数。
Function.prototype.a = "a";
Object.prototype.b = "b";
function Person(){}
console.log(Person); //functionPerson()
let p = newPerson();
console.log(p); //Person {} 对象
console.log(p.a); //undefined
console.log(p.b); //b
p.__proto__ === Person.prototype;Person.prototype.constructor === Person
当调用某种方法或查找某种属性时,首先会在自身调用和查找,如果自身并没有该属性或方法,则会去它的__proto__属性中调用查找,也就是它构造函数的prototype中调用查找,如果构造函数中也没有该属性方法,则会去构造函数的隐式原型中查找,一直到null,就这样形成原型链。
继承方式
原型链继承:
Child()的原型作为Parent()的实例来继承Parent()的方法属性
因为所有实例都继承原型方法属性,其中一个实例对原型属性值更改后,所有实例调用该属性的值全部更改
function Parent() {}
Parent.prototype.parentSay = function() {
return 'i am parent';
}
function Child() {}
Child.prototype.childSay = function(){
return 'i am child';
}
Child.prototype = new Parent();
var par = newParent();
var kid = newChild();
console.log(kid.parentSay()); //i am parent
构造函数继承:
在子类的构造函数内部通过call或apply来调用父类构造函数
无法实现函数的复用
function People() {
this.name = ['zhangsan','lisi','wangwu'];
}
function Person() {
People.call(this);
}
var per1 = newPerson();
per1.name.push('zhanliu');
console.log(per1.name); //["zhangsan", "lisi", "wangwu","zhanliu"]
var per2 = newPerson();
console.log(per2.name); //["zhangsan", "lisi", "wangwu"]
组合继承:
将原型链继承和构造函数继承结合,最常用的继承模式
原型链继承共享的属性和方法,构造函数继承实例属性
function People(num) {
this.num = num;
this.name = ['zhangsan','lisi','wangwu'];
}
People.prototype.numCount = function(){
console.log(this.num);
}
function Person(num) {
People.call(this, num);
}
//继承方式
Person.prototype = newPeople();
Person.prototype.constructor = Person;
var per1 = newPerson(10);
per1.name.push('zhaoliu');
console.log(per1.name); //["zhangsan", "lisi", "wangwu","zhanliu"]
per1.numCount(); //10
var per2 = newPerson(20);
console.log(per2.name); //["zhangsan", "lisi", "wangwu"]
per2.numCount(); //20
数组常用方法
改变原数组:
尾部删除pop()
尾部添加push()
头部删除shift()
头部添加unshift()
排序sort()
颠倒数组元素reverse()
删除或插入元素splice();
不会改变元素组:
合并数组concat()
拼接数组元素join()
截取元素slice()
indexOf(),lastIndexOf(),toString()
数据存储
Cookie:用于客户端与服务端通信,也具有本地存储的功能
localStorage,sessionStorage:专门用于存储
区别:
大小:Cookie容量为4K,因为用于客户端与服务端通信,所有http都携带,如果太大会降低效率; localStorage,sessionStorage大小为5M。
失效时间:Cookie会在浏览器关闭时删除,除非主动设置删除时间;localStorage一直都在直到用户主动删除或清除浏览器缓存;sessionStorage在浏览器关闭时删除。