二、JavaScript 基础
1、javascript
的typeof
返回哪些数据类型
object
number
function
boolean
underfind
string
1
2
3
4
5
6
7
8typeof null;//object
typeof isNaN;//function
typeof isNaN(123);//boolean
typeof [];//object
Array.isArray(); //es5
toString.call([]);//”[object Array]”
var arr=[];
arr.constructor;//Array
2、例举 3 种强制类型转换和 2 种隐式类型转换?
- 强制(
parseInt
,parseFloat
,Number()
) - 隐式(
==
)1==”1”//true
null==undefined//true
3、split()
join()
的区别
- split 是切割成数组的形式
- join 是将数组转换成字符串
4、数组方法pop()
push()
unshift()
shift()
push()
尾部添加pop()
尾部删除unshift()
头部添加shift()
头部删除
5、事件绑定和普通事件有什么区别
传统事件绑定和符合 W3C 标准的事件绑定有什么区别?1
2div1.onclick=function(){};
<button onmouseover=""></button>
- 如果说给同一个元素绑定了两次或者多次相同类型的事件,那么后面的绑定会覆盖前面的绑定
- 不支持 DOM 事件流 事件捕获阶段目标元素阶段=>事件冒泡阶段
addEventListener
- 如果说给同一个元素绑定了两次或者多次相同类型的事件,所以的绑定将会依次触发
- 支持 DOM 事件流的
- 进行事件绑定传参不需要
on
前端1
2addEventListener("click",function(){},true);
//此时的事件就是在事件冒泡阶段执行
- ie9 开始,
ie11 edge:addEventListener
- ie9 以前:
attachEvent('onclick')/detachEvent('onclick')
- 进行事件类型传参需要带上
on
前缀 - 这种方式只支持事件冒泡,不支持事件捕获
事件绑定是指把事件注册到具体的元素之上,普通事件指的是可以用来注册的事件
事件委托是什么
符合 W3C 标准的事件绑定 addEventLisntener / attachEvent
让利用事件冒泡的原理,让自己的所触发的事件,让他的父元素代替执行!IE 和 DOM 事件流的区别
- 执行顺序不一样
- 参数不一样
- 事件加不加
on
this
指向问题
6、IE 和标准下有哪些兼容性的写法
1 | var ev = ev || window.event; |
7、 call 和 apply 的区别
call 和 apply 相同点:
都是为了用一个本不属于一个对象的方法,让这个对象去执行1
2
3
4toString.call([],1,2,3)
toString.apply([],[1,2,3])
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
8、、JavaScript
this
指针、闭包、作用域
this
:指向调用上下文闭包:内层作用域可以访问外层作用域的变量
- 闭包就是能够读取其他函数内部变量的函数。
- 闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数
作用域:定义一个函数就开辟了一个局部作用域,整个 js 执行环境有一个全局作用域
9、如何阻止事件冒泡和默认事件
1 | e.stopPropagation();//标准浏览器 |
阻止默认事件:
为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止1
2return false;
e.preventDefault();
10、添加、删除、替换、插入到某个接点的方法
1 | obj.appendChild()//向节点添加最后一个子节点 |
11、javascript 的本地对象,内置对象和宿主对象
- 本地对象为
array
obj
regexp
等可以new
实例化 - 内置对象为
Global
Math
等不可以实例化的 - 宿主为浏览器自带的
document
,window
等
12、document load
和document ready
的区别
Document.onload
是在结构和样式加载完才执行jswindow.onload
:不仅仅要在结构和样式加载完,还要执行完所有的样式、图片这些资源文件,全部加载完才会触发window.onload
事件Document.ready
原生种没有这个方法,jquery
中有$().ready(function)
13、“==”和“===”的不同
前者会自动转换类型、后者不会
1
21=='1'
null==undefined===
先判断左右两边的数据类型,如果数据类型不一致,直接返回false
之后才会进行两边值的判断
14、javascript 的同源策略
- 一段脚本只能读取来自于同一来源的窗口和文档的属性,这里的同一来源指的是主机名、协议和端口号的组合
http
,ftp
:协议- 主机名;
localhost
- 端口名:
80
(http协议的默认端口) https
:默认端口是8083
同源策略带来的麻烦:ajax
在不同域名下的请求无法实现,
如果说想要请求其他来源的js
文件,或者json
数据,那么可以通过jsonp
来解决
15、编写一个数组去重的方法
1 | var arr=[1,1,3,4,2,4,7];=>[1,3,4,2,7]; |
一个比较简单的实现就是:
- 先创建一个空数组,用来保存最终的结果
- 循环原数组中的每个元素
- 再对每个元素进行二次循环,判断是否有与之相同的元素,如果没有,将把这个元素放到新数组中
- 返回这个新数组
1
2
3
4
5
6
7
8
9
10
11function oSort(arr) {
var result ={};
var newArr=[];
arr.forEach(item=>{
if(!result[item]) {
newArr.push(item)
result[arr] = 1
}
});
return newArr
}
16、JavaScript 是一门什么样的语言,它有哪些特点?
- 运行环境:浏览器中的 JS 引擎(
v8
) 语言特性:面向对象,动态语言:
1
2
3//动态语言的特性
var num = 10;//num是一个数字类型
num = "jim";//此时num又变成一个字符串类型我们把一个变量用来保存不同数据类型的语言称之为一个动态语言
- 静态语言:
c# java c c++
- 静态语言在声明一个变量就已经确定了这个变量的数据类型
- 而且在任何时候都不可以改变他的数据类型
17、JavaScript 的数据类型都有什么?
- 基本数据类型:String,Boolean,number,undefined,object,Null
- 引用数据类型:Object(Array,Date,RegExp,Function)
那么问题来了,如何判断某变量是否为数组数据类型?
- 方法一. 判断其是否具有“数组性质”,如
slice()
方法。可自己给该变量定义slice
方法,故有时会失效 - 方法二.
obj instanceof Array
在某些IE版本中不正确 方法三. 方法一二皆有漏洞,在
ECMA Script5
中定义了新方法Array.isArray()
, 保证其兼容性,最好的方法如下:1
2toString.call(18);//”[object Number]”
toString.call(“”);//”[object String]”解析这种简单的数据类型直接通过
typeof
就可以直接判断1
2
3
4
5
6
7//toString.call常用于判断数组、正则这些复杂类型
toString.call(/[0-9]{10}/)//”[object RegExp]”
if(typeof Array.isArray==="undefined"){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg)==="[object Array]"
};
}
- 方法一. 判断其是否具有“数组性质”,如
18、已知 ID 的Input
输入框,希望获取这个输入框的输入值,怎么做?(不使用第三方框架)
1 | document.getElementById('ID').value |
19、希望获取到页面中所有的checkbox
怎么做?(不使用第三方框架)
1 | var domList = document.getElementsByTagName('input') |
20、设置一个已知 ID 的 DIV 的 html 内容为xxxx,字体颜色设置为黑色(不使用第三方框架)
1 | var dom = document.getElementById('ID'); |
21、当一个 DOM 节点被点击时候,我们希望能够执行一个函数,应该怎么做?
- 直接在 DOM 里绑定事件:
<div></div>
- 在 JS 里通过
onclick
绑定:xxx.onclick = test
- 通过事件添加进行绑定:
addEventListener(xxx, 'click', test)
- 那么问题来了,
Javascript
的事件流模型都有什么?- “事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
- “事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
- “ DOM 事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
22、看下列代码输出为何?解释原因。
1 | var a; |
解释:undefined
是一个只有一个值的数据类型,这个值就是“undefined
”,在使用 var 声明变量但并未对其赋值进行初始化时,这个变量的值就是undefined
。而b由于未声明将报错。注意未申明的变量和声明了未赋值的是不一样的。undefined
会在以下三种情况下产生:
- 一个变量定义了却没有被赋值
- 想要获取一个对象上不存在的属性或者方法:
- 一个数组中没有被赋值的元素
注意区分undefined
跟not defnied
(语法错误)是不一样的
23、看下列代码,输出什么?解释原因。
1 | var a = null; |
解释:null
是一个只有一个值的数据类型,这个值就是null
。表示一个空指针对象,所以用typeof
检测会返回”object
”。
24、看下列代码,输出什么?解释原因。
1 | var undefined;//此时undefined这个变量的值是undefined |
此时会把布尔类型的值转换为数字类型 true = 1 false = 0
1
2
3
4
5
62 == true; // false
0 == false; // true
0 == ''; // true
NaN == NaN; // false
[] == false; // true
[] == ![]; // true
undefined
与null
相等,但不恒等(===
)
一个是number
一个是string
时,会尝试将string
转换为number
尝试将boolean
转换为number
,0
或1
尝试将Object
转换成number
或string
,取决于另外一个对比量的类型
所以,对于0
、空字符串
的判断,建议使用 ===
。===
会先判断两边的值类型,类型不匹配时为false
。
那么问题来了,看下面的代码,输出什么,foo 的值为什么?1
2
3var foo = "11" + 2 - "1";
console.log(foo);//111
console.log(typeof foo);//Number
执行完后foo
的值为111
,foo
的类型为number
。
25、看代码给答案。
1 | var a = new Object(); |
26、已知数组var stringArray = [“This”, “is”, “Baidu”, “Campus”]
,Alert
出“This is Baidu Campus
”。
1 | alert(stringArray.join("")) |
已知有字符串foo=”get-element-by-id”
,写一个function
将其转化成驼峰表示法”getElementById
”。1
2
3
4
5
6
7
8
9function combo(msg) {
var arr = msg.split("-"); //[get,element,by,id]
for (var i = 1; i < arr.length; i++) {
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1, arr[i].length-1); //Element
}
msg = arr.join(""); //msg='getElementById'
return msg;
}
(考察基础 API )
27、var numberArray = [3,6,2,4,1,5]
; (考察基础 API )
1) 实现对该数组的倒排,输出[5, 1, 4, 2, 6, 3]1
numberArray.reverse();//[5, 1, 4, 2, 6, 3]
2) 实现对该数组的降序排列,输出[ 6, 5, 4, 3, 2, 1]1
numberArray.sort((x,y) => y-x);//[6, 5, 4, 3, 2, 1]
28、输出今天的日期,以 YYYY-MM-DD 的方式,比如今天是 2014 年 9 月 26 日,则输出 2014-09-26
1 | var d = new Date(); |
29、将字符串“<tr><td>{$id}</td><td>{$name}</td></tr>
”中的{$id}
替换成10
,{$name}
替换成Tony
(使用正则表达式)
1 | '<tr><td>{$id}</td><td>{$id}_{$name}</td></tr>'.replace(/{\$id}/g, ’10′).replace(/{\$name}/g, ‘Tony’); |
30、为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写一个函数escapeHtml
,将<, >, &, “
进行转义
1 | function escapeHtml(str) { |
31、foo = foo||bar
,这行代码是什么意思?为什么要这样写?
这种写法称之为短路表达式
答案:if(!foo) foo = bar; //如果foo存在,值不变,否则把bar的值赋给foo。
短路表达式:作为”&&
”和”||
”操作符的操作数表达式,这些表达式在进行求值时,只要最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。
注意if
条件的真假判定,记住以下是false
的情况:空字符串
、false
、undefined
、null
、0
32、看下列代码,将会输出什么?(变量声明提升)
1 | var foo = 1; |
答案:输出undefined
和 2
。上面代码相当于:1
2
3
4
5
6
7var foo = 1;
function(){
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo); // 2;
}
函数声明与变量声明会被JavaScript
引擎隐式地提升到当前作用域的顶部,但是只提升名称不会提升赋值部分。
33、用js
实现随机选取10–100
之间的10
个数字,存入一个数组,并排序。
1 | var iArray = []; |
34、把两个数组合并,并删除第二个元素。
1 | var array1 = ['a','b','c']; |
35、怎样添加、移除、移动、复制、创建和查找节点(原生 JS ,实在基础,没细写每一步)
创建新节点
1
2
3createDocumentFragment() //创建一个 DOM 片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点添加、移除、替换、插入
1
2
3
4appendChild() //添加
removeChild() //移除
replaceChild() //替换
insertBefore() //插入查找
1
2
3getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的 Name 属性的值
getElementById() //通过元素 Id ,唯一性
36、有这样一个URL
:http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e
,请写一段JS
程序提取URL
中的各个GET
参数(参数名和参数个数不确定),将其按key-value
形式返回到一个json
结构中,如{a:’1′, b:’2′, c:”, d:’xxx’, e:undefined}
。
1 | function serilizeUrl(url) { |
37、正则表达式构造函数var reg=new RegExp(“xxx”)
与正则表达字面量var reg=//
有什么不同?匹配邮箱的正则表达式?
答案:当使用RegExp()
构造函数的时候,不仅需要转义引号(即\
”表示”),并且还需要双反斜杠(即\\
表示一个\
)。使用正则表达字面量的效率更高。
邮箱的正则匹配:1
var regMail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((.[a-zA-Z0-9_-]{2,3}){1,2})$/;
看下面代码,给出输出结果。1
2
3
4
5for (var i=1; i <= 3; i++) {
setTimeout(function () {
console.log(i);
},0);
};
答案:4 4 4。
原因:Javascript
事件处理器在线程空闲之前不会运行。追问,如何让上述代码输出1 2 3
?1
2
3
4
5
6
7
8for (var i=1 ;i <= 3 ; i++) {
setTimeout( (function (a) { //改成立即执行函数
console.log(a);
}) (i) , 0 );
};
1 //输出
2
3
38、写一个function
,清除字符串前后的空格。(兼容所有浏览器)
使用自带接口trim()
,考虑兼容性:1
2
3
4
5
6
7
8
9if (!String.prototype.trim) {
String.prototype.trim = function() {
return this.replace(/^\s+/, "").replace(/\s+$/,"");
//\s匹配空白字符:回车、换行、制表符tab空格
}
}
// test the function
var str = " \t\n test string ".trim();
alert(str == "test string"); // alerts "true"
39、Javascript
中callee
和caller
的作用?
arguments.callee
:获得当前函数的引用caller
是返回一个对函数的引用,该函数调用了当前函数;callee
是返回正在被执行的function
函数,也就是所指定的function
对象的正文。
那么问题来了?如果一对兔子每月生一对兔子;一对新生兔,从第二个月起就开始生兔子;假定每对兔子都是一雌一雄,试问一对兔子,第 n 个月能繁殖成多少对兔子?(使用callee
完成)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var result=[];
function fn(n){ //典型的斐波那契数列
if(n==1){
return 1;
}else if(n==2){
return 1;
}else{
if(result[n]){
return result[n];
}else{
//argument.callee()表示fn()
result[n]=arguments.callee(n-1)+arguments.callee(n-2);
return result[n];
}
}
}