1、javascript 的 typeof 返回哪些数据类型
object
number
function
boolean
undefined
string
2、例举 3 种强制类型转换和 2 种隐式类型转换?
强制(parseInt(),parseFloat(),Number())
隐式(==)
1==”1”//true
null==undefined//true
3、split()和 join() 的区别
前者是切割成数组的形式,
后者是将数组转换成字符串
4、数组方法 pop() push() unshift() shift()
Push()尾部添加
pop()尾部删除
Unshift()头部添加
shift()头部删除
5、事件绑定和普通事件有什么区别
传统事件绑定和符合 W3C 标准的事件绑定有什么区别?
div1.onclick=function(){}; <button onmouseover=””></button>
1、如果说给同一个元素绑定了两次或者多次相同类型的事件,那么后面的绑定会覆盖前面 的绑定 ;
2、不支持 DOM 事件流 事件捕获阶段目标元素阶段=>事件冒泡阶段
addEventListener
1、 如果说给同一个元素绑定了两次或者多次相同类型的事件,所有的绑定将会依次触发
2、 支持 DOM 事件流
3、 进行事件绑定传参不需要 on 前缀 addEventListener(“click”,function(){},true);//此时的事件就是在事件冒泡阶段执行
ie9 开始,ie11edge:addEventListener
ie9 以前:attachEvent/detachEvent
1、 进行事件类型传参需要带上 on 前缀
2、 这种方式只支持事件冒泡,不支持事件捕获 事件绑定是指把事件注册到具体的元素之上,普通事件指的是可以用来注册的事件
6、IE 和 DOM 事件流的区别
1.执行顺序不一样、
2.参数不一样
3.事件加不加 on
4.this 指向问题
IE9 以前:attachEvent(“onclick”)、detachEvent(“onclick”)
IE9 开始跟 DOM 事件流是一样的,都是 addEventListener
7、IE 和标准下有哪些兼容性的写法
var ev=ev||window.event
document.documentElement.clientWidth || document.body.clientWidth
var target = ev.srcElement||ev.target
8、call 和 apply 的区别
call 和 apply 相同点:
都是为了用一个本不属于一个对象的方法,让这个对象去执行
toString.call([],1,2,3)
toString.apply([],[1,2,3])
Object.call(this,obj1,obj2,obj3)
Object.apply(this,arguments)
9、b 继承 a 的方法
考点:继承的多种方式
js继承有5种实现方式:
1、继承第一种方式:对象冒充
function Parent(username){
this.username = username;
this.hello = function(){
alert(this.username);
}
}
function Child(username,password){
//通过以下3行实现将Parent的属性和方法追加到Child中,从而实现继承
//第一步:this.method是作为一个临时的属性,并且指向Parent所指向的对象,
//第二步:执行this.method方法,即执行Parent所指向的对象函数
//第三步:销毁this.method属性,即此时Child就已经拥有了Parent的所有属性和方法
this.method = Parent;
this.method(username);//最关键的一行
delete this.method;
this.password = password;
this.world = function(){
alert(this.password);
}
}
var parent = new Parent("zhangsan");
var child = new Child("lisi","123456");
parent.hello(); //zhangsan
child.hello(); //lisi
child.world(); //123456
2、继承第二种方式:call()方法方式
call方法是Function类中的方法
call方法的第一个参数的值赋值给类(即方法)中出现的this
call方法的第二个参数开始依次赋值给类(即方法)所接受的参数
function test(str){
alert(this.name + " " + str);
}
var object = new Object();
object.name = "zhangsan";
// 此时,第一个参数值object传递给了test类(即方法)中出现的this,而第二个参数"langsin"则赋值给了test类(即方法)的str
test.call(object,"langsin"); //zhangsan langsin
function Parent(username){
this.username = username;
this.hello = function(){
document.write(this.username + "<br>");
}
}
function Child(username,password){
Parent.call(this,username);
this.password = password;
this.world = function(){
document.write(this.password+ "<br>");
}
}
var parent = new Parent("zhangsan");
var child = new Child("lisi","123456");
parent.hello(); //zhangsan
child.hello(); //lisi
child.world(); //123456
3、继承的第三种方式:apply()方法方式
apply方法接受2个参数,
A、第一个参数与call方法的第一个参数一样,即赋值给类(即方法)中出现的this
B、第二个参数为数组类型,这个数组中的每个元素依次赋值给类(即方法)所接受的参数
function Parent(username){
this.username = username;
this.hello = function(){
alert(this.username);
}
}
function Child(username,password){
Parent.apply(this,new Array(username));
this.password = password;
this.world = function(){
alert(this.password);
}
}
var parent = new Parent("zhangsan");
var child = new Child("lisi","123456");
parent.hello(); //zhangsan
child.hello(); //lisi
child.world(); //123456
4、继承的第四种方式:原型链方式
即子类通过prototype将所有在父类中通过prototype追加的属性和方法都追加到Child,从而实现了继承
function Person(){
}
Person.prototype.hello = "hello";
Person.prototype.sayHello = function(){
alert(this.hello);
}
function Child(){
}
Child.prototype = new Person();//这行的作用是:将Parent中将所有通过prototype追加的属性和方法都追加到Child,从而实现了继承
Child.prototype.world = "world";
Child.prototype.sayWorld = function(){
alert(this.world);
}
var c = new Child();
c.sayHello();
c.sayWorld();
5、继承的第五种方式:混合方式
混合了call方式、原型链方式
function Parent(hello){
this.hello = hello;
}
Parent.prototype.sayHello = function(){
alert(this.hello);
}
function Child(hello,world){
Parent.call(this,hello);//将父类的属性继承过来
this.world = world;//新增一些属性
}
Child.prototype = new Parent();//将父类的方法继承过来
Child.prototype.sayWorld = function(){//新增一些方法
alert(this.world);
}
var c = new Child("zhangsan","lisi");
c.sayHello();
c.sayWorld();
10、JavaScript this 指针、闭包、作用域
this:指向调用上下文
闭包:内层作用域可以访问外层作用域的变量
作用域:定义一个函数就开辟了一个局部作用域,整个 js 执行环境有一个全局作用域
11、事件委托是什么
符合 W3C 标准的事件绑定 addEventLisntener/attachEvent
利用事件冒泡的原理,让自己本身要触发的事件,让他的父元素代替执行!
12、闭包是什么,有什么特性,对页面有什么影响
闭包就是能够读取其他函数内部变量的函数。
闭包的缺点:滥用闭包函数会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量
永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数。
13、如何阻止事件冒泡和默认事件
阻止事件冒泡
e. stopPropagation();//标准浏览器
event.canceBubble=true;//ie9 之前
阻止默认事件:
为了不让 a 点击之后跳转,我们就要给他的点击事件进行阻止
return false
e.preventDefault();
14、添加 删除 替换 插入到某个接点的方法
obj.appendChild() //添加
obj.insertBefore() //插入。原生的 js 中不提供 insertAfter();
obj.replaceChild()//替换
obj.removeChild()//删除
15、javascript 的本地对象,内置对象和宿主对象
本地对象
Object、Function、Array、String、Number、Date、RegExp、Boolean、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError等可以 用new 实例化的对象
由此得出,JS的本地对象就是ECMA-262中定义的类(引用类型)
内置对象
ECMA-262把内置对象定义为:由ECMAScript提供实现的、独立于宿主环境的所有对象,在ECMAScript程序开始执行时出现。
这意味着内置对象都是已经实例化好的,不需要我们再进行实例化了,这里我们首先会想到的就是Math对象。
ECMA-262定义的内置对象只有两个:Global和Math。
(本地对象和内置对象都是独立于宿主对象,根据定义可以看出来内置对象也是本地对象,在JS中所有的内置对象都是本地对象)。
Math对象是我们经常用到的,但是Global就比较少见了。其实我们经常用到Global对象,只是没有用Global这个名字。
Global对象是一个比较特殊的对象,它是一个全局对象,在程序中只有一个,它的存在伴随着整个程序的生命周期,全局对象不能通过名字来访问,但是它有一个window属性,这个属性指向它本身。
大家也要清楚,在ECMAScript中不存在独立的函数,所有的函数都应该是某个对象的方法。类似于isNaN()、parseInt()、parseFloat()等方法都是Global对象的方法。
宿主对象
宿主对象:由ECMAScript实现的宿主环境提供的对象。
可能这样不是很好理解,上面已经说过了宿主环境包括Web浏览器,所以我们可以这样理解,浏览器提供的对象都是宿主对象。
也可以这样理解,因为本地对象是非宿主环境的对象,那么非本地对象就是宿主对象,即所有的BOM对象和DOM对象都是宿主对象。
那么还有一种对象,那就是我们自己定义的对象,也是宿主对象。
最简单的理解:ECMAScript官方未定义的对象都属于宿主对象。
如浏览器自带的 document,window 等
总结
官方的定义太绕口,还不好理解。说的简单点:
本地对象
就是ECMAScript中定义好的对象,如String、Date等,
内置对象
是本地对象中比较特殊的一种,它不用实例化,包括Global和Math,
宿主对象
就是BOM、DOM和自己定义的对象。
16、document load 和 document ready 的区别
Document.onload
是在结构和样式加载完就执行 js
window.onload
:不仅仅要在结构和样式加载完,还要执行完所有的样式、图片这些资源文 件,全部加载完才会触发 window.onload 事件
Document.ready 原生中没有这个方法,jquery 中有 $(document).ready(function)
17、”==”和“===”的不同
前者会自动转换类型
后者不会
1==”1”
null==undefined
===先判断左右两边的数据类型,如果数据类型不一致,直接返回 false
之后才会进行两边值的判断
18、JavaScript的同源策略
详细解答请点击链接进入我的另一篇博客查看(JavaScript的同源策略详解)
19、编写一个数组去重的方法
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>去除一个数组中重复的元素</title>
</head>
<body>
<script type="text/javascript">
/*
* 方法一:
*/
var arr = [1, 0, 2, 1, 8, 1, 0, 10, 8];
var obj = {};
var temp = [];
for(var i=0; i<arr.length; i++) {
if(!obj[arr[i]]) {
obj[arr[i]] = 1;
temp.push(arr[i]);
}
}
console.log(temp); //1,0,2,8,10
/*
* 方法二:
*/
var arr2= [1, 0, 2, 1, 8, 1, 0, 10, 8, 9, 11];
var arr3 = [];
for(var i=0; i<arr2.length; i++) {
//indexOf()方法从数组的开头(位 置 0)开始向后查找,返回索引号
//若未找到则返回-1
if((arr3.indexOf(arr2[i])) < 0) {
arr3.push(arr2[i]);
}
}
console.log(arr3);//1,0,2,8,10,9,11
/*
* 方法三:
*/
//filter():对数组中的每一项运行给定函数,返回该函数会返回 true的项组成的数组。
var arr4 = [0, 10, 22, 0, 10, 1, 2, 3, 1];
var arr5 = arr4.filter(function(element, index, arr4) {
return arr4.indexOf(element) == index;
});
console.log(arr5); //0,10,22,1,2,3
</script>
</body>
</html>
21、JavaScript 的数据类型都有什么?
基本数据类型:String,Boolean,number,undefined,object,Null
引用数据类型:Object(Array,Date,RegExp,Function)
那么问题来了,如何判断某变量是否为数组数据类型?
方法一.判断其是否具有“数组性质”,如 slice()方法。可自己给该变量定义 slice 方法,
故有时会失效
方法二.obj instanceof Array
在某些 IE 版本中不正确
方法三.方法一二皆有漏洞,在 ECMA Script5 中定义了新方法 Array.isArray()
, 保证其兼
容性,最好的方法如下:
toString.call(18);//”[object Number]”
toString.call(“”);//”[object String]”
解析这种简单的数据类型直接通过 typeof 就可以直接判断
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]"
};
}
22、已知 ID 的 Input 输入框,希望获取这个输入框的输入值,怎么做?(不使 用第三方框架)
document.getElementById(“ID”).value
23、希望获取到页面中所有的 checkbox 怎么做?(不使用第三方框架)
var domList = document.getElementsByTagName(‘input’)
var checkBoxList = [];//返回的所有的 checkbox
var len = domList.length; //缓存到局部变量
while (len--) { //使用 while 的效率会比 for 循环更高
if (domList[len].type == ‘checkbox’) {
checkBoxList.push(domList[len]);
}
}
24、设置一个已知 ID 的 DIV 的 html 内容为 xxxx,字体颜色设置为黑色(不使用 第三方框架)
var dom = document.getElementById(“ID”);
dom.innerHTML = “xxxx”
dom.style.color = “#000”
25、当一个 DOM 节点被点击时候,我们希望能够执行一个函数,应该怎么做?
直接在 DOM 里绑定事件:<div onclick=”test()”></div>
在 JS 里通过 onclick 绑定:xxx.onclick = test
通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)
那么问题来了,Javascript 的事件流模型都有什么?
“事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
“事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
“DOM 事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
26、看下列代码输出为何?解释原因。
var a;
alert(typeof a); // “undefined”
//alert(b); // 报错
b=10;
alert(typeof b);//”number”
解释:Undefined 是一个只有一个值的数据类型,这个值就是“undefined”,在使用 var
声明变量但并未对其赋值进行初始化时,这个变量的值就是 undefined。而 b 由于未声明将
报错。注意未申明的变量和声明了未赋值的是不一样的。
undefined 会在以下三种情况下产生:
- 1、 一个变量定义了却没有被赋值
- 2、 想要获取一个对象上不存在的属性或者方法:
- 3、 一个数组中没有被赋值的元素
注意区分 undefined 跟 not defnied(语法错误)是不一样的
27、看下列代码,输出什么?解释原因。
var a = null;
alert(typeof a); //object
解释:null 是一个只有一个值的数据类型,这个值就是 null。表示一个空指针对象,所以
用 typeof 检测会返回”object”。
28、看下列代码,输出什么?解释原因。
var undefined;//此时 undefined 这个变量的值是 undefined
undefined == null; // true
1 == true; // true
此时会把布尔类型的值转换为数字类型
true=1 false=0
2 == 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 的值为什么?
var foo = "11"+2-"1";
console.log(foo);//111
console.log(typeof foo);
执行完后 foo 的值为 111,foo 的类型为 number。
29、看代码给答案。
var a = new Object();
a.value = 1;
b = a; //{value:1}
b.value = 2;
alert(a.value);//2
答案:2(考察引用数据类型细节)
30 、 已 知 数 组 var stringArray = [“This”, “is”, “Baidu”, “Campus”],Alert 出”This is Baidu Campus”。
答案:
alert(stringArray.join(“ ”))
31、已知有字符串 foo=”get-element-by-id”,写一个 function 将其转化成驼峰表示法”:getElementById”。
function 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)
32、输出今天的日期,以 YYYY-MM-DD 的方式,比如今天是 2014 年 9 月 26 日, 则输出 2014-09-26
var d = new Date();
// 获取年,getFullYear()返回 4 位的数字
var year = d.getFullYear();
// 获取月,月份比较特殊,0 是 1 月,11 是 12 月
var month = d.getMonth() + 1;
// 变成两位
month = month < 10 ? '0' + month : month;
// 获取日
var day = d.getDate();
day = day < 10 ? '0' + day : day;
alert(year + '-' + month + '-' + day);
33、将字符串”<tr><td>{$id}</td><td>{$name}</td></tr>”
中的{$id}
替换 成 10,{$name}
替换成 Tony
(使用正则表达式)
答案:
"<tr><td>{$id}</td><td>{$name}</td></tr>".replace(/{\$id}/g, '10').replace(/{\$name}/g, 'Tony');
34、为了保证页面输出安全,我们经常需要对一些特殊的字符进行转义,请写 一个函数 escapeHtml,将<, >, &, \
进行转义
function escapeHtml(str) {
//[<>”&]:中括号中字符只要其中的一个出现就代表满足条件
//给 replace 第二个参数传递一个回调函数,回调函数中参数就是匹配结果,如果匹配不到就是null
return str.replace(/[<>"&]/g, function(match) {
switch (match) {
case "<":
return "<";
case ">":
return ">";
case "&":
return "&";
case '\"':
return """;
}
});
}
35、foo=foo||bar ,这行代码是什么意思?为什么要这样写?
这种写法称之为短路表达式
意思为:if(!foo) foo = bar; //如果 foo 存在,值不变,否则把 bar 的值赋给 foo。
短路表达式:作为”&&”和”||”操作符的操作数表达式,这些表达式在进行求值时,只要
最终的结果已经可以确定是真或假,求值过程便告终止,这称之为短路求值。
注意 if 条件的真假判定,记住以下是 false 的情况:
空字符串、false、undefined、null、0
36、看下列代码,将会输出什么?(变量声明提升)
var foo = 1;
function(){
console.log(foo); //undefined
var foo = 2;
console.log(foo); //2
}
答案:输出 undefined 和 2。上面代码相当于:
var foo = 1;
function(){
var foo;
console.log(foo); //undefined
foo = 2;
console.log(foo); // 2;
}
函数声明与变量声明会被 JavaScript 引擎隐式地提升到当前作用域的顶部,但是只提升名
称不会提升赋值部分。
37、用 js 实现随机选取 10–100 之间的 10 个数字,存入一个数组,并排序。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript">
/*
* 随机选取[10, 100]内的10个数
*并排序
* Math.floor(num); 取得num整数部分
* Math.ceil(num); 取得大于等于num的最小整数
* Math.round(num); num四舍五入后的整数
*/
var pushArray = []; //存放取出的数
//产生一个10到100之间的数
function getRandom(start, end) {
var choice = end - start + 1;
return Math.floor(Math.random() * choice + start);
}
//Math.random()就是获取 0-1 之间的随机数(永远获取不到 1)
for(var i=0; i<10; i++) {
var result = getRandom(10, 100);
pushArray.push(result);
}
pushArray.sort();
console.log(pushArray); //12,19,21,28,34,39,44,54,65,86
</script>
</body>
</html>
38、把两个数组合并,并删除第二个元素。
var array1 = ['a','b','c'];
var bArray = ['d','e','f'];
var cArray = array1.concat(bArray);
cArray.splice(1,1); //splice() 方法用于插入、删除或替换数组的元素。
splice()方法如下所示:
//splice()方法
/*
* 删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数
* 会影响原始数组
*/
var fruits = ["apple", "mango", "banana", "pear"];
var fruit1 = fruits.splice(0, 2);
document.write(fruits + "<br>"); //banana,pear
document.write(fruit1); //返回删除的项apple,mango
document.write("<br>");
/*
* 插入:可以向指定位置插入任意数量的项,只需提供 3个参数:
* 起始位置、0(要删除的项数) 和要插入的项
*/
var fruit2 = ["apple", "mango", "banana", "pear"];
var fruit3 = fruit2.splice(2, 0, "strawberry", "lalala");
document.write(fruit2 + "<br>");//apple,mango,strawberry,lalala,banana,pear
document.write(fruit3 + "<br>");//未删除项,所以返回空数组
/*
* 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,
* 只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。
* 插入的项数不必与删除的项数相等。
*/
var fruit4 = ["apple", "mango", "banana", "pear"];
var fruit5 = fruit4.splice(1, 2, "aaa", "bbb", "ccc");
document.write("<br>" + fruit4 + "<br>");//apple,aaa,bbb,ccc,pear
document.write(fruit5); // 返回删除的项mango,banana
39、怎样添加、移除、移动、复制、创建和查找节点
详细讲解请见本人另一篇博客((完全详解)JavaScript 添加、复制、移除、移动、创建和查找节点)】
40、有这样一个 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}。
截取问号后的字符串,按‘&’间隔拆分,再按‘=’拆分,再分情况判断。
var url='http://item.taobao.com/item.htm?a=1&b=2&c=&d=xxx&e';
function nameAndValue(url){
url=url.split('?')[1];
var group=url.split('&');
var res={};
for(var i=0;i<group.length;i++){
start=group[i].indexOf('=');
if(start!=-1){
name=group[i].slice(0,start);
value=group[i].slice(start+1,group[i].length);
res[name]=value;
}else{
res[group[i]]=undefined;
}
}
for(var key in res) {
document.write(key + ":" + " " + res[key]);
document.write("<br>");
}
}
nameAndValue(url);
结果:
a: 1
b: 2
c:
d: xxx
e: undefined
41、正则表达式构造函数 var reg=new RegExp(“xxx”)与正则表达字面量 var reg=//有什么不同?匹配邮箱的正则表达式?
答案:当使用 RegExp()构造函数的时候,不仅需要转义引号(即\”表示”),并且还需要
双反斜杠(即\表示一个\)。
使用正则表达字面量的效率更高。
邮箱的正则匹配:
var regMail = /^[A-Za-z\d]+[A-Za-z\d\-_\.]*@([A-Za-z\d]+[A-Za-z\d\-]*\.)+[A-Za-z]{2,4}$/;
24.看下面代码,给出输出结果。
for(var i=1;i<=3;i++){
setTimeout(function(){
console.log(i);
}, 0);
};
答案:4 4 4。
原因: Javascript 事件处理器在线程空闲之前不会运行。
追问,如何让上述代码输出 1 2 3?
for(var i=1;i<=3;i++){
setTimeout((function(a){ //改成立即执行函数
console.log(a);
})(i), 0);
};
1 //输出
2
3
42、写一个 function,清除字符串前后的空格。(兼容所有浏览器)
使用自带接口 trim(),考虑兼容性:
if (!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"