1. 介绍JS的基本数据类型
Undefined、Null、Boolean、Number、String 可以用typeof操作符来检测
2. 介绍JS有哪些内置对象? Object是JavaScript中所有对象的父对象。
数据封装类对象:Object、Array、Boolean、Number和String
其他对象:Function、Arguments、Math、Date、RegExp、Error
3. 什么是JS中的事件委托? 事件委托是解决“事件处理程序过多”的方案。事件委托利用了事件冒泡,只指定一个事件处理,就可以管理某一类型的所有事件。
也就是说:利用事件冒泡的原理,把相关事件绑定到父级元素上,触发执行效果。
例如:click事件会一直冒泡到document层。也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不必给每个可单击的元素分别添加事件处理程序。
4. 什么是Ajax,其核心是什么? Ajax全称为Asynchronous JavaScript And XML
向服务器发送异步请求的时候,我们不必等待结果返回,而是同时做其他的事情,等到结果返回后,程序会根据设定(callback)进行后续操作,此时,页面也不会发生刷新,提高用户体验。
Ajax的核心对象就是xhr,XMLHttpRequest
发生Ajax请求的过程可分为以下六步:
创建XMLHttpRequest对象,也就是创建一个异步调用对象。
创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息。
设置响应HTTP请求状态变化的函数
发送HTTP请求
获取异步调用返回的数据
使用JS操作DOM或数据驱动框架来实现局部刷新
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304)
var data = JSON.parse(xhr.responseText);
callback(data);
}
};
xhr.open(‘get’,url,true);
xhr.send(null);
5. JS中如何实现继承? 在传统的面向对象语言中,类从其他类继承属性。然后在JavaScript中,继承可以发生在没有类的继承关系的对象之间。这种继承机制就是利用原型对象。 先简单回顾一下构造函数、原型和对象实例这三者的关系:每个构造函数都有一个原型对象,相对应地这个原型对象包含一个指向构造函数的指针,而该构造函数new出来的每个对象实例都有一个指向原型对象的内部指针。
原型链继承 JavaScript内建的继承方法被称为原型对象链,又可称为原型对象继承。原型对象的属性可由对象实例访问,这就是继承的一种形式。对象实例继承了原型对象的属性。因为原型对象也是一个对象,它也有自己的原型对象并可以继承其属性,这就原型链:对象继承其原型对象,而原型对象继承它的原型对象,以此类推。 所有对象,包括我们自己定义的对象都自动继承自Object。确切地说,所有对象都继承自Object.prototype。
下面是一种常用的继承方式,利用了原型链和构造函数相结合的技术,利用原型链来实现对方法的继承,借用构造函数来实现对属性的继承(主要针对一些数组、对象等引用类型的属性)。
function SuperType(name){
this.name = name;
this.colors = [“red”,”yellow”];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name,age){
//借用父类的构造函数,这样SubType的实例中就有了name和colors这两个实例属性,这两个属性就是每个实例独有的了
SuperType.call(this,name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
//这是把SubType的constructor属性改回来,创建SubType实例时调用SubType的构造函数
SubType.prototype.constructor = SubType;
//在SubType的新原型上添加一个方法
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType(“zhu”,24);
instance1.colors.push(“black”);
alert(instance1.colors); //red,yellow black
instance1.sayName(); //zhu
instance1.sayAge(); //24
var instance2 = new SubType(“li”,23);
instance2.colors.push(“blue”);
alert(instance2.colors); //red,yellow blue
instance2.sayName(); //li
instance2.sayAge(); //23
深拷贝继承 参考阮一峰老师的一篇博客。
var Chinese = { nation: ‘中国’};
var Doctor = { career: ‘医生’};
//让“医生”继承“中国人”,变成一位中国医生。
//把父对象的属性全部拷贝给子对象,也能实现继承
//由于父对象的属性可能是数组或对象,所以需要用深拷贝
function deepCopy(p, c){
var c = c || {};
for(var i in p){
if(typeof p[i] === ‘object’){
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else{
c[i] = p[i];
}
}
return c;
}
Chinese.place = [‘北京’,’上海’,’广州’];
//深拷贝
var Doctor = deepCopy(Chinese);
Doctor.place.push(‘大理’);
console.log(Chinese.place);
console.log(Doctor.place);
JavaScript中的作用域链? 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节。
当需要从局部函数查找某一属性或方法时,如果当前作用域没有找到该属性或方法,就会上溯到上层作用域查找,直至全局函数,这种组织形式就是作用域链。
6. 什么是闭包?
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
闭包的特性:
1. 函数内再嵌套函数
2. 内部函数可以引用外层的参数和变量 3. 参数和变量不会被垃圾回收机制回收
例子:
function createFunction(){
var result = new Array();
for(var i=0; i<10; i++){
result[i] = (function(num){
return function(){
return num;
};
})(i);
}
return result;
}
上面这个例子中有两个闭包,外层的那个立即执行的匿名函数是一个闭包。在调用每个匿名函数时,我们传入了变量i,由于函数参数是按值传递,所以就会将变量i的当前值赋值给参数num。而在每个匿名函数内部,我们创建并返回了一个可以访问num的闭包。这样一来,result数组中的每个函数都有了自己num变量的一个副本,因此就可以返回各自不同的数值了。
new操作符具体干了什么?
7. 创建一个空对象,并且this变量引用该对象,同时还继承了该函数的原型。
属性和方法被加入到this引用的对象中。
新创建的对象由this所引用,并且最后隐式返回this。
JSON的了解? JSON是一种轻量级的数据交换格式。 它是基于JavaScript的一个子集。数据格式简单,易于读写,占用带宽小。
8. eval是做什么的? eval函数的功能是把对应的字符串解析成JS代码并运行。
应该避免使用eval,不安全,且非常消耗性能(2次处理,一次解析成JS语句,一次执行)
9. null和undefined的区别? null表示没有对象,即此处不应该有值 undefined表示缺少值,此处应该有一个值,但是还没有定义。
10. 如何解决跨域问题? JSONP、window.name、window.postMessage、iframe
11. 模块化开发怎么做? 立即执行函数,不暴露私有成员。
12. 函数中的arguments是什么,是数组吗?若不是,如何将它转化为真正的数组? arguments是一个类数组对象(它并不是Array的实例),它可以通过方括号语法访问每个元素,也可以使用length属性来确定调用函数时传递进来了多少个参数。 Array.prototype.slice.call(arguments)
13. 列举JavaScript中的typeof函数的可能结果,如何区分:{}和[]类型?
typeof的值可能有:”number”,”string”,”boolean”,”object”,”undefined”,”function”
区分{}和[]:
1. [].constructor === Array,t={},t.constructor === Object
2. [] instanceof Array ==> true
t = {},t instanceof Object ==> true
14. Function中的call、apply、bind的区别是什么?请分别写出示例代码
bind()方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数,它的参数是bind()的其他参数和其原本参数。
bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值。JavaScript新手经常犯的一个错误就是将一个方法(假设方法中用到了this对象)从对象中拿出来,然后再调用,并且希望方法中的this是原来的对象。如果 不做特殊处理的话,一般会丢失原来的对象。用原来的函数和原来的对象创建一个绑定函数,可以漂亮地解决这个问题:
this.x = 9;
var module = {
x: 81,
getX: function(){ return this.x }
}
module.getX(); //81
var retrieveX = module.getX;
//注意这段代码要在非严格模式下运行,严格模式下会报错
//因为严格模式下this为undefined
retrieveX(); //9,因为此时方法中的this指向的是全局对象
//用bind方法解决这个问题
var boundGetX = retrieve.bind(module);
boundGetX(); //81
apply()和call()很类似,都是在指定指定this值和参数的情况下调用某个函数。差别只是apply()方法的参数是以数组或类数组对象的形式存在。call()方法的参数是一个参数列表(逗号隔开)。
实例:比如之前讲到的把函数的arguments类数组对象转成一个数组的方法:Array.prototype.slice.call(arguments)
使用jQuery,找到id为“selector”的select标签中拥有’data-target’属性,且值为“isme”的option的值? $(‘select#selector>option[data-target=”isme”]’).val()
15. 设计一个算法,合并两个有序数组为一个有序数组?
与归并排序类似
var a = [3,6,8,9,15];
var b = [1,2,5,7,12,16];
var result = [];
function mergeArray(a,b,result){
var i=0,j=0,index=0;
while(i<a.length && j<b.length){
if(a[i] <= b[j]){
result[index++] = a[i++];
} else{
result[index++] = b[j++];
}
}
while(i<a.length){
result[index++] = a[i++];
}
while(j<b.length){
result[index++] = b[j++];
}
}