基础JavaScript篇

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

排序算法

升序:

var numberArray = [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 = new RegExp( 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(typeof obj === 'object');  //true
console.log(typeof arr === '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(){
var Child = new Object();
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";
};
var x =new Parent();

(3) 原型模式

function Parent(){
};
Parent.prototype.name="欲泪成雪";
Parent.prototype.age="20";
var x =new Parent();

(4)混合的构造函数,原型方式(推荐)

function Parent(){
  this.name="欲泪成雪";
  this.age=22;
};
Parent.prototype.lev=function(){
  return this.name;
};
var x =new Parent();

(5)动态原型方式

function Parent(){
  this.name="欲泪成雪";
  this.age=22;
;
if(typeof Parent._lev=="undefined"){
Parent.prototype.lev=function(){
  return this.name;
}
Parent._lev=true;
}
};
var x =new Parent();

请写出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){
var evt = 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.应用方法一

export const promiseDemo=()=>{
new Promise((resolve,reject)=>{
    resolve(()=>{
        let a=1;
        return ++a;
    }).then((data)=>{
        console.log(data)//data值为++a的值
    }).catch(()=>{//错误执行这个
 
    })
})
}

2.应用方法二

export const 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在浏览器关闭时删除。

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值