1、本文主体源自:http://www.cnblogs.com/coco1s/p/4029708.html,有兴趣的可以直接去那里看,也可以看看我整理加拓展的。
2、js是一门什么样的语言及特点?
js是一种基于对象和事件驱动的并具有相对安全性的客户端脚本语言。也是一种广泛用于web客户端开发的脚本语言,常用来给html网页添加动态功能,如响应用户的各种操作。
主要的目的是为了解决服务器端语言遗留的速度问题,为客户提供更流畅的浏览效果。
(详细拓展:http://www.360doc.com/content/14/0317/11/10186276_361233415.shtml)
3、js的数据类型?
基本数据类型:String、boolean、Number、undefined、null
引用数据类型:Object、Array、Date、RegExp、Function
拓展:如何判断数组数据类型?
1、通过专有方法判断如:push(),pop(); //可自己给变量定义该方法,有时失效
2、 obj instanceof Array 返回值判断;
3、es5和jquery都有方法Array.isArray()。
4、toString.call(param) 判断;返回格式 [object Undefined] 5、obj.constructor === Function 返回值判断
4、获取所有的checkbox?
var domlist = document.getElementsByTagName("input");
var checkboxlist = [];
var len = domlist.length;
for (var i = 0; i < len; i++) {
if(domlist[i].type == "checkbox"){
checkboxlist.push(domlist[i])
}
}
//各大主流浏览器中,for与while在平时使用中效率上for循环效率略优。
5、绑定事件的方式?
1、直接在dom里绑定:<div onclick="test()"></div>
2、在js中通过onclick绑定:xxx.onclick=test;
3、通过事件绑定:dom.addEventListener("click",test,boolean)
(拓展:js事件流模型?)
“事件冒泡”:事件由最具体的元素接收,然后逐级向上传播;
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体元素;
“dom事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡;
(附:事件流详解)
ie事件流:冒泡型事件:button->div->body
netscape事件流:捕获型事件:body->div->button
dom事件模型:body->div->button->button->div->body;
dom事件流同时支持两种事件模型:但是捕获事件先发生,从document对象开始,也在document对象结束
ie9以下不支持addEventListener/removeEventListener,采用attachEvent/detachEvent
(无关东东css:<!--[if lt IE 9]><![endif]-->)
(附:阻止事件传播)
w3c中,使用stopPropagation()方法阻止冒泡;阻止默认事件:preventDefault();
ie中,cancelBubble = true阻止事件冒泡;阻止默认事件:window.event.returnValue = false;
6.什么是Ajax和JSON,它们的优缺点?
Ajax(Asynchronous Javascript And XML/异步的javascript和xml)。
优点:
可以使得页面不重载全部内容的情况下加载局部内容,降低数据传输量。
避免用户不断刷新或者跳转页面,提高用户体验。
缺点:
对搜索引擎不友好。
要实现ajax下的前后退功能成本较大
可能造成请求数的增加
跨域问题限制
JSON:json是一种轻量级的数据交换格式,ECMA(欧洲计算机制造商协会)的一个子集;
优点:轻量级,占用带宽小、易于人的阅读和编写,便于机器(js)解析,支持复合数据类型(数组,对象,字符串,数字),能直接为服务器端代码使用,大大简化了服务器端和客户端的代码开发量。
缺点:相对xml通用性较差,数据可描述性较差;
(拓展:json与xml的区别?)
xml定义:可拓展标记语言,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的语言。xml是SGML(标准通用标记语言)的子集,非常适合web传输。
xml提供统一的方法来描述和交换独立于应用程序或供应商的结构化数据。
xml优点:
1、格式统一,符合标准;
2、容易与其他系统进行交互,数据共享比较方便
缺点:
1、xml文件格式文件庞大,格式复杂,传输占用更多带宽
2、服务器和客户端都需要花费大量代码来解析xml,服务器和客户端代码变得异常复杂和不容易维护。
3、客户端不同浏览器之间解析xml的方式不一致,需要重复编写很多代码。
4、服务器端和客户端解析xml花费更多资源和时间
与json的优缺点比较?
1、可读性、可拓展性都很出色,但是xml的编码难度更高。
2、json的解码难度几乎为0,而xml得考虑子父节点;
3、xml的通用性更广,json则广泛应用于前端。
4、json相对xml,数据体积更小;与js交互更方便;
5、json对数据的描述性比xml较差;
6、json的无论是传播还是解析速度远远快于xml;
7、什么情况会出现undefined?
当只声明变量,并未赋值初始化的时候这个变量的值就是undefined;
(拓展:解释原因?)
var a=null;
console.log(typeof a); // object
null是一个只有一个值的数据类型,这个值就是null。表示一个空指针对象。所以typeof返回object;
8、双等号的类型转换?
var undefined;
undefined == null; // true
1 == true; // true
2 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true
// alert(!![]) //true
// alert(![]) //false
// alert([] == 0) //true
// alert(false == 0) //true
分析:undefined与null相等 但不全等(===)
当为number与string时,会将string转换为number;
number和boolean时,会将boolean转换为number
number或string与Object,会将Object转换成number或string
(附:js中的数据类型转换?)
函数转换:parseInt()、parseFloat()、toString()
强类型转换:Boolean()、Number()、String()
弱类型转换:“==”、“-”、“+”、if()
(拓展:for循环中的效率问题?)
1.for(var i=0;i<arr.length;i++)
2.for(var i in arr)
3.for(var i=0,len=arr.length;i<len;i++)
第三种效率更高!
在大数据下:
第三种方式比第一种执行速度快3~4倍;
至于第三种比第三种快100多倍开外(详细数据:http://www.111cn.net/wy/js-ajax/39368.htm)
9、基础算法?已知:var str="get-element-by-id",写一个函数转化成驼峰形式(你懂得)?
function Naizi(str){
var arr = str.split("-");
var target = "";
for(var i=0,len=arr.length;i<len;i++){
target+=arr[i].substr(0,1).toUpperCase()+arr[i].substr(1);
}
return target;
}
10、基础API?
数组:
var numberArray = [3,6,2,4,1,5];
倒序:numberArray.reverse();
降序:numberArray.sort(function(a-b){return b-a})
a.concat(b,c,d)
日期:
输出YYYY-MM-DD
function getYMD(){
var date = new Date();
var y = date.getFullYear();
var m = date.getMonth()+1;
var d = date.getDate();
function getDouble(str){
var str;
if(str < 10){
return str = "0"+str;
}else{
return str = str;
}
}
return y +"-"+getDouble(m)+"-"+getDouble(d);
}
(值得一提:date.getDay() 返回星期0~6 星期日~星期六)
11、正则?
var str = ”<tr><td>{$id}</td><td>{$name}</td></tr>”的{$id}替换成10,{$name}替换成Tony
var target = str.replace(/{\$id}/,"10").replace(/{\$name}/,"Tony");
(拓展:tirm方法实现)
var str = " sdasad ";
function trim(str){
return str.replace(/(^\s*)|(\s*$)/g,"");
}
(拓展:转义字符方法实现)
function escapeHTML(str){
return str.replace(/[<>"&]/g,function(match,key){
switch(match){
case '<':
return '\<';
break;
case '>':
return '\>';
break;
case '"':
return '\"';
break;
case '&':
return '\&';
break;
}
})
}
(拓展:正则构造函数var reg=new RegExp("xxx")与正则字面量形式var reg=//有什么不同?匹配邮箱?)
使用RegExp()构造函数的时候,不仅需要转义引号(“\”),并且还需要双反斜杠\\表示一个\。使用正则字面量形式效率更高;
邮箱匹配:
var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-]{2,3})$/;
12、短路表达式 || &&?
foo = foo || bar;
如果foo 为真 foo = foo; 否则 foo = bar;
|| 第一个为真则返回第一个,否则返回第二个;
&& 第一个为假则返回第一个,否则返回第二个;
作用:精简代码,不过可读性较低;
13、随机取10个10-100数?
function getNumArr(n){
var arr = [];
for(var i = 0;i <n;i++){
arr.push(parseInt(Math.random()*90+10))
}
return arr;
}
14、dom增删查改?
增:
document.createElement(tag);
document.createTextNode();
document.createDocumentFragment()
dom.appendChild(sondom);
dom.insertBefore(newdom,targetdom);
删:
document.removeChild();
改:
document.replaceChild();
查:
getElementById()
getElementsByTagName()
getElementsByName();
15、字符串操作?
var str = 'http://item.taobao.com/item.html?a=1&b=2&c=&d=xxx&e';
//将GET参数按照键值对的形式输出json
function getGEt(str){
var dataStr = str.split("?")[1];
var result = {};
if(dataStr.indexOf("&") > 0){
var bigArr = dataStr.split("&");
for(var i = 0,len = bigArr.length;i<len;i++){
var smallArr = bigArr[i].split("=");
result[smallArr[0]] = smallArr[1];
}
}else{
var arr = dataStr.split("=");
result[arr[0]] = arr[1];
}
return result;
}
16、闭包的使用?
for(var i = 0,len=domlist.length;i<len;i++){
domlist[i].onclick = function(){
console.log(i);
}
}
都输出domlist.length;
onclick 是一个异步函数;当onclick执行的时候i此时变成了domlist.length;
解决:(闭包)
for(var i=0,len=domlist.length;i<len;i++){
domlist[i].onclick = (function(a){
return function(){
console.log(a)
}
})(i);
}
//也可以设置私有属性;
17、js中callee和caller?
caller是返回一个对函数的引用,该函数调用了当前函数;
callee是返回正在被执行的function函数,也就是所指定的对象的正文;
(注:callee是arguments的属性,只有当函数被调用的时候才会生成arguments,未调用时为null,所以调用callee将会报错)
//斐波那契数列
function getFibonacci(n) {
var fibarr = [];
var i = 0;
while(i<n) {
if(i<=1) {
fibarr.push(i);
}else{
fibarr.push(fibarr[i-1] + fibarr[i-2])
}
i++;
}
return fibarr;
}
18、实现函数clone,包括Number、String、Object、Array、Boolean?
function clone(param){
var result;
switch(typeof param){
case "object":
if(param instanceof Array){
result = [];
for(var i=0,len=param.length;i<len;i++){
result.push(param[i]);
}
return result;
} else if(param instanceof Object){
result = {};
for(var key in param){
result[key] = param[key];
}
return result;
}else{
return result = param;
}
break;
default:
return result = param;
break;
}
}
19.老掉牙的数组去重?
var arr = [123,"1",123,12,312,3,123,"123",1,23,123,12,312,3,123,123,123,123,12] function gotU(arr){
var result = [];
var json = {};
for(var i = 0,len=arr.length;i<len;i++){
var temp = arr[i];
var type = typeof temp;
if(!json[temp]){
json[temp] = [type];
result.push(temp);
}else{
if(json[temp].indexOf(type) < 0){
json[temp].push(type);
result.push(temp);
}
}
}
return result;
}
20.提取对象属性与方法?
粗壮的旺财是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。
function Dog(){
this.name = "粗壮的旺财";
this.type = "cute";
this.animalkind = "dog";
}
Dog.prototype={
sound:function(){
alert("wow SB");
},
seeMaster:function(){
this.sound();
},
seeMasterBeingB:function(){
var bitches = 50;
for(var i=0;i<bitches;i++){
this.seeMaster();
}
}
}
小猪和粗壮的旺财一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。
function MadDog(){
this.name = "小猪";
}
MadDog.prototype = new Dog();
MadDog.prototype.foundSomeoneIsAGay=function(){
var self = this;
this.timer = setInterval(function(){
self.seeMaster();
},500)
}
21、编写一个js,输入指定类型选择器返回匹配的dom节点(id,class,tag),考虑浏览器兼容性和性能;
function select(str){
if(str){
var doms;
var result = [];
var first = str.charAt(0);
var other = str.substr(1);
if(first == "#"){
doms = document.getElementById(other);
result.push(doms);
return result;
}else if(first == "."){
if(document.getElementsByClassName){
doms = document.getElementsByClassName(other);
return getArr(doms);
}else{
doms = document.getElementsByTagName("*");
for(var i = 0,len = doms.length;i<len;i++){
if(hasClass(doms[i],other)){
result.push(doms[i])
}
}
return result;
}
}else{
doms = document.getElementsByTagName(str);
return getArr(doms);
}
}
}
function getArr(param){
var result = null;
try{
result = Array.prototype.slice.call(param,0) //非ie
}catch(e){
result = [];
for(var i=0,len=param.length;i<len;i++){
result.push(param[i]);
}
}
return result;
}
function hasClass(dom,classname){
var clas = dom.className;
var arr = [];
if(dom && clas){
arr = clas.split(" ");
for (var i = 0,len = arr.length; i < len; i++) {
if(arr[i] == classname) return true;
}
return false;
}
return false;
}
22、评价代码,给出意见。
if(window.addEventListener){
var addListener = function(el,type,listener,useCapture){
el.addEventListener(type,listener,useCapture);
};
}else if(document.all){
addListener = function(el,type,listener){
el.attachEvent("on"+type,function(){
listener.apply(el);
});
}
}
不应在if和else语句中声明addListener函数,应该先声明;
不需使用window.addEventListener或document.all来进行检测浏览器,应该使用能力检测;
由于attachEvent在IE中有this指向问题,所以调用它时需要处理一下
改进:
function addEvent(elem,type,handler){
if(elem.addEventListener){
elem.addEventListener(type,handler,false);
}else if(elem.attachEvent){
elem.attachEvent("on"+type,handler);
}else{
elem["on"+type] = handler;
}
}
(拓展:阻止默认事件与冒泡事件)
function preventEvent(e){
var e = e || window.event;
e.preventEvent || e.returnValue = false;
e.stopPropagation || e.cancelBubble = true;
}
23、String对象添加方法,例:addSpace("hello world") // -> 'h e l l o w o r l d';
String.prototype.addSpace = function() {
if(this.length>0){
var arr = this.split("");
var tempArr = [];
var target;
for(var i=0,len=arr.length;i<len;i++){
if(arr[i] != " "){
tempArr.push(arr[i]);
}
}
return target = tempArr.join(" ");
}
return this;
};
(附:函数声明与函数表达式的区别?)
在js中,解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁的,
解析器会率先读取函数声明,并使其在执行任何代码之前可用(也就是函数声明提升),
至于函数表达式要等到解析器执行到它所在的代码,才会真正解析执行。(只有变量名称提升)
24、定义一个方法代理console.log。
function log(){
console.log.apply(null,arguments);
}
(拓展:apply与call的区别?)
apply与call的作用相同,即调用一个对象的一个方法,改变该方法的this的指针。
在第二个参数:apply传入的是一个参数数组,而call传入的是离散型参数。
25、在js中什么是伪数组?如何转化成真数组?
伪数组:无法直接调用数组的方法,但是仍含有length属性。
getElementsByTagName/getElementsByClassName/childNodes/arguments 都是伪数组;
通过使用Array.prototype.slice.call(fakeArray)将伪数组转化为真数组;
(拓展:给log添加前缀?)
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift("aa");
console.log.apply(null,args);
}
26、作用域与this?
var User = {
count:1,
getCount:function(){
return this.count;
}
}
console.log(User.getCount()) //1
var fn = User.getCount;
console.log(fn()); //undefined
为什么?
fn是在window的上下文中被执行的,所以会访问不到count属性。也就是说this指向的是window.
最好的方法还是使用混合对象:构造函数+原型对象构建
function User(){
this.count = 1;
}
User.prototype={
getCount:function(){
return this.count;
}
}
var fn = new User();
console.log(fn.getCount());
27、原生js的window.onload与jQuery的$(document).ready(function(){})有什么不同?如何用原生js实现ready方法?
window.onload方法必须等到页面内包括图片的所有元素加载完毕后才能执行。
$(document).ready()是DOM结构绘制完毕后就执行,不必等到加载完毕。
原生实现:
function ready(fn){
var d = document; //提高性能
if(d.addEventListener){
d.addEventListener("DOMContentLoaded",function(){
//注销事件,避免反复触发
d.removeEventListener("DOMContentLoaded",arguments.callee,false);
fn();
},false)
}else if(d.attachEvent){ //ie9以下
d.attachEvent("onreadystatechange",function(){
d.detachEvent("onreadystatechange",arguments.callee);
fn();
})
}
}
28、原生js对某个节点实行拖拽?(思路)
1、给需要拖拽的节点绑定mousedown,mousemove,mouseup事件;
2、mousedown事件触发后,开始拖拽
3、mousemove时,通过e.clientX和clientY获取拖拽位置,实时更新位置;
4、mouseup时,拖拽结束。
5、注意浏览器边界情况。
(附例)
function drop(id){
var dom = document.getElementById(id);
var w = dom.clientWidth;
var h = dom.clientHeight;
dom.addEventListener("mousedown",function(e){
var flag=true;
var e = e || window.event;
var d = document.documentElement;
var docW = d.clientWidth;
var docH = d.clientHeight;
var dx = e.clientX-this.offsetLeft;
var dy = e.clientY-this.offsetTop;
this.addEventListener("mousemove",function(e){
var e = e || window.event;
var left = e.clientX-dx;
var top = e.clientY-dy;
if(flag){
if(left<=0){
left = 0;
}else if(left >= docW- w){
left = docW - w;
}
if(top <= 0 ){
top = 0;
}else if(top >= docH - h){
top = docH - h;
}
this.style.left = left+"px";
this.style.top = top+"px";
}
})
this.addEventListener("mouseup",function(){
flag = false;
})
})
}
29、下列函数的作用?空白区域填写?
(function(window) {
function fn(str) {
this.str = str;
}
fn.prototype.format = function() {
var arg = ______;
return this.str.replace(_____, function(a, b) {
return arg[b] || "";
});
}
window.fn = fn;
})(window);
(function() {
var t = new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>');
console.log(t.format('http://www.alibaba.com', 'Alibaba', 'Welcome'));
})();
//使用format方法将函数参数替换掉{0}这样的内容,返回一个格式化的结果;
//1.arguments 2./{(\d+)}/g
30.使用js面向对象介绍自己。
使用json或对象都很不错。
31.原生js实现Ajax的原理。
Ajax(Asynchronous JavaScript and XML)表示异步的js与xml。有别于传统web的同步开发方式。
原理:通过XMLHttpRequest对象向服务器发送异步请求,从服务器获得数据,然后使用js操作DOM更新数据。
该对象是ajax的核心机制,他是在IE5中首先引入的,是一种支持异步请求的技术。
通过ajax可以及时的向服务器提出请求和处理响应,而不阻塞用户,达到无刷新更新部分页面的效果。
XMLHttpRequest这个对象的属性有:
onreadystatechange 每次状态改变所触发事件的事件处理程序;
responseText 从服务器进程返回数据的字符串形式;
responseXML 从服务器进程返回的DOM兼容的文档数据对象;
status 从服务器返回的数字代码,常见的200(客户端请求成功,已就绪)和404(请求资源不存在)
statusText 伴随状态码的字符串信息 (eg:200 OK)
readyState 对象状态值
0(未初始化状态)对象已建立或已被abort()方法重置,尚未调用open方法。
1(初始化状态)open()方法已经调用,但是send()方法为调用。请求还没有被发送。
2(发送数据)send()方法法以调用,HTTP请求已发送到Web服务器。未接收到响应。
3(数据传送中)所有响应头部都已经接收到。响应体开始接受但未完成。
4(完成加载)HTTP响应已经完全接收。
(拓展:封装ajax?)
ajax({
url: "./TestXHR.aspx", //请求地址
type: "POST", //请求方式
data: { name: "super", age: 20 }, //请求参数
dataType: "json",
success: function (response, xml) {
// 此处放成功后执行的代码
},
error: function (status) {
// 此处放失败后执行的代码
}
});
function ajax(options) {
options = options || {};
options.type = (options.type || "GET").toUpperCase();
options.dataType = options.dataType || "json";
var params = formatParams(options.data);
var xhr;
//创建 - 第一步
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if(window.ActiveObject) { //IE6及以下
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//连接 和 发送 - 第二步
if (options.type == "GET") {
xhr.open("GET", options.url + "?" + params, true);
xhr.send(null);
} else if (options.type == "POST") {
xhr.open("POST", options.url, true);
//设置表单提交时的内容类型
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(params);
}
//接收 - 第三步
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
var status = xhr.status;
if (status >= 200 && status < 300 || status == 304) {
options.success && options.success(xhr.responseText, xhr.responseXML);
} else {
options.error && options.error(status);
}
}
}
}
//格式化参数
function formatParams(data) {
var arr = [];
for (var name in data) {
arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
}
arr.push(("v=" + Math.random()).replace("."));
return arr.join("&");
}
(拓展:什么是jsonp和pjax?)
Jsonp:(JSON with Padding/json的补充)是一种跨域的请求方式。
原理:利用script标签可以跨域请求的特点,由其src属性发送请求到服务器,服务器返回js代码(类似于callback(data),其中data就是传回的数据,通过网页端js函数callback引用),这种方式和通过script标签引用外部文件的原理是一样的。
Jsonp由两部分组成:回调函数和数据,回调函数一般是由网页端控制,将回调函数名作为参数发往服务器端,服务器端把该函数和数据拼成字符串返回。
(详细链接:http://kb.cnblogs.com/page/139725/)
pjax:pjax是一种基于ajax+history.pushState的新技术,该技术可以无刷新改变页面的内容,并且可以改变页面的URL。
(关键点:可以实现ajax无法实现的后退功能)pajax是ajax+pushState的封装,同时支持本地存储、动画等多种功能。目前支持jquery、qwrap、kissy等多种版本。
(详细拓展:https://developer.mozilla.org/en-US/docs/Web/API/History_API,http://www.cnblogs.com/flash3d/archive/2013/10/23/3384823.html)