1. JS 中使用 typeof 能得到哪些类型?
undefined string boolean object number function
console.log(typeof undefined);
// "undefined"
console.log(typeof 'sfsgsdf');
// string
console.log(typeof 123);
// number
console.log(typeof true);
// boolean
console.log(typeof {a:1});
// object
console.log(typeof ['ddf']);
// object
console.log(typeof null);
// object
console.log(typeof function (){});
// function
console.log(typeof console.log);
// function
2. 何时使用 === 何时使用 ==
if ( obj.a == null) { }
这里的 obj.a == null 相当于 obj.a === null || obj.a == undefined,
除了上面这种情况都采用 ===。
解释:
==:等同,比较运算符,两边值类型不同的时候,先进行类型转换,再比较
===:恒等,严格比较运算符,不做类型转换,类型不同就是不等
补充:Object.is()是ES6新增的用来比较两个值是否严格相等的方法,与===的行为基本一致,
console.log(Object.is(123,'123')); // false
console.log(Object.is(345,345)); // true
console.log(NaN === NaN); // false
console.log(Object.is(NaN,NaN)); // true
console.log(+0=== -0); // true
console.log(Object.is(+0,-0)); // false
3. JS 中有哪些内置函数
Array Object String Boolean Function Number RegExp Error
补充:Math 是个内置对象
4. JS 变量按照存储方式区分为哪些类型,并描述其特点
(1) 值类型:
值类型的变量是存放在栈区的,栈区中包括了变量的标识符以及变量所对应的值
var a = 12;
var b = a;
console.log(a); // 12
console.log(b); // 12
b = 20;
console.log(a); // 12
console.log(b); // 20
(2) 引用类型:
引用类型的变量也是存放在栈区的,不同的是,引用类型在栈区中存放的是变量标识符以及变量所对应值的引用地址,而变量所对应的值被存放在堆区中。
所以下列代码给 b 赋值的时候是把 a 的引用地址赋给了 b,这就是修改 b.age后,a.age 也发生了变化的原因
var a = { age: 12 };
var b = a;
console.log(a.age); // 12
console.log(b.age); // 12
b.age = 20;
console.log(a.age); // 20
console.log(b.age); // 20
5. 理解 JSON
JSON 是 JS 的一个对象,有以下方法:
(1) 将 json 对象转换成字符串
JSON.stringify({a:"aaa","b":1214});
// '{"a":"aaa","b":1214}'
(2) 将字符串转换成 json 对象
JSON.parse('{"a":"aaa","b":1214}');
JSON.parse("{'a':'aaa','b':1214}"); // 报错
注意:JSON 对象应该是双引号
6. 如何准确判断一个变量是数组类型
方法1:利用 instanceof
var obj = {a:0,b:1};
var arr = [1,2,3,4,'fff'];
console.log(obj instanceof Array); // false
console.log(arr instanceof Array); // true
实际上这个方法不能正确判断变量的类型
方法二:利用 Object.prototype.toString 方法
<script>
var obj = {a:0,b:1};
var arr = [1,2,3,4,'fff'];
// Object.prototype.toString.call(obj) // [object Object]
// Object.prototype.toString.call(arr) // [object Array]
function isArrayFn (o){
var str = Object.prototype.toString.call(o);
if(str === '[object Array]') {
return true;
}else {
return false;
}
}
console.log(isArrayFn(obj)); // false
console.log(isArrayFn(arr)); // true
</script>
这是常用的方法:Object.prototype.toString, 还可以用来区别 Function Object Number等
console.log(Object.prototype.toString.call("dfgs分dfgdf"));//[object String]
console.log(Object.prototype.toString.call(123));//[object Number]
console.log(Object.prototype.toString.call(true));//[object Boolean]
console.log(Object.prototype.toString.call(undefined));//[object Undefined]
console.log(Object.prototype.toString.call(null));//[object Null]
console.log(Object.prototype.toString.call({name: "gdsfgs"}));//[object Object]
console.log(Object.prototype.toString.call(function(){}));//[object Function]
console.log(Object.prototype.toString.call([1,2,3]));//[object Array]
console.log(Object.prototype.toString.call(new Date));//[object Date]
console.log(Object.prototype.toString.call(/\d/));//[object RegExp]
方法三: ES6 中的 Array.isArray()
用 ES6 中的 Array.isArray() 判断非常简单,
<script>
var obj = {a:0,b:1};
var arr = [1,2,3,4,'fff'];
console.log(Array.isArray(obj)); // false
console.log(Array.isArray(arr)); // true
</script>
7. 描述 new 一个对象的过程
- 创建一个新对象
- this 指向这个新对象
- 执行代码:对 this 赋值
- 返回 this
8. Jquery(或其他框架) 源码中如何使用原型链
<div id="box">内容</div>
<script>
function Elem (id) {
this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val){
var elem = this.elem;
if(val){
// 设置
elem.innerHTML = val;
return this; // 链式调用
}else {
// 获取
return elem.innerHTML
}
}
Elem.prototype.on = function (type, Fn){
var elem = this.elem;
elem.addEventListener(type,Fn,false);
}
// var oBox = new Elem('box');
// oBox.html('点击我').on('click', function (){ alert('点击了') });
function Jquery(id) {
return new Elem(id);
}
window.$ = window.jQuery = Jquery;
$('box').html('点击我').on('click', function (){ alert('点击了') });
</script>
关于更多原型链的知识点,请移步:面试知识点之原型链
8. 说一下对变量提升的理解
JS 的预解析:
在当前作用域下,JS 代码在正式开始执行之前,进行的一些解析工作: 会把带有 var 和 function 关键字的事先声明,并在内存中安排好,这个过程也可以理解为变量提升,然后再从上到下执行 JS 语句,例如:
- 把 var 声明的 num 变量的初始化提升到该作用域的最前面:
console.log(num);
var num = 123;
// 结果:undefined
// 代码实际运行过程
var num; // var num = undefined;
console.log(num);
num = 123;
- 把 var 声明的 fn 变量的初始化提升到该作用域的最前面:
console.log(fn);
var fn = function (){};
// 结果:undefined
// 代码实际运行过程
var fn; // var fn= undefined;
console.log(fn);
fn= function (){};
- 把 function 声明的整个函数提升到该作用域的最前面:
console.log(f);
function f(){}
// 结果:ƒ f(){}
// 代码实际运行过程
function f(){}
console.log(f);
- 再看看下面的情况:
console.log(a);
var a = 1;
function a(){};
console.log(a);
// 结果:
// ƒ a(){}
// 1
// 代码实际运行过程:
var a; // var a= undefined;
function a(){};
console.log(a);
a = 1;
console.log(a);
9. 说明 this 几种不同的使用场景
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call、apply、bind
10. 创建 10 个 <a> 标签,点击的时候弹出来对应的序号
考点:作用域
<script>
var oDiv = document.createElement('div'),
oBody = document.body;
for (var i = 0; i < 10; i++) {
(function (i){
var link = document.createElement('a');
link.innerHTML = '第' + (i +1) + '个A '
link.addEventListener('click',function (ev){
var ev = ev || window.event;
ev.preventDefault();
alert(i+1);
},false);
oDiv.appendChild(link);
}(i))
}
oBody.appendChild(oDiv);
</script>
ES6 用 let 的块级作用域实现方法 :
<script>
var oDiv = document.createElement('div'),
oBody = document.body;
for (let i = 0; i < 10; i++) {
var link = document.createElement('a');
link.innerHTML = '第' + (i +1) + '个A '
link.addEventListener('click',function (ev){
var ev = ev || window.event;
ev.preventDefault();
alert(i+1);
},false);
oDiv.appendChild(link);
}
oBody.appendChild(oDiv);
</script>
11. 如何理解作用域
执行环境:全局执行环境 和 局部执行环境
全局执行环境是最外围的执行环境,全局执行环境被认为是 window 对象,它所对应的就是全局作用域,
即在全局执行环境下定义的变量,叫全局变量,对任何内部函数来说,都是可以访问的,
局部执行环境一般指函数内部或者固定的代码片段内(ES6中引进块级作用域的概念),函数内定义的就是局部变量,只有在该函数内部及内部所有的函数才可以访问到这个变量,
特别需要注意的是: 非严格模式下,在任何地方不声明直接使用变量,变量会成为全局变量,在严格模式下,不允许变量不声明直接使用
比如:
var num = 0;
function fn(){
num1 = 123;
var num2 = 456;
var num3 = 789;
console.log(num3);
}
fn(); // 789
console.log(num); // 结果: 0,num 是全局变量
console.log(num1); // 结果: 123, num1 是全局变量
console.log(num2); // 报错,num2 是 fn 函数的局部变量,函数外部访问不到
12. 实际开发中闭包的应用
13. 同步和异步的区别
- 同步会阻塞代码的执行,而异步不会
- alert 是同步,setTimeout 是异步
14. 前端使用异步的场景有哪些
- 定时任务: setTimeout、setInterval
- 网络请求:ajax 请求、动态 <img> 加载
- 事件绑定
15. 获取 xxxx-xx-xx 格式的日期
<script>
// 获取 xxxx-xx-xx 格式的日期
function formatDate (date) {
if ( !date ) {
date = new Date()
}
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
month = addZero(month)
day = addZero(day)
return year + '-' + month + '-' + day
}
function addZero (num) {
return num < 10 ? '0' + num : num
}
var d = formatDate(new Date())
console.log(d)
</script>
16. 获取随机数,要求是长度一致的字符串格式
<script>
function getRandom() {
var random = Math.random() + '0000000000'
return random.slice(0,11)
}
getRandom()
</script>
17. 写一个能遍历数组和对象的 forEach 函数
<script>
var a = [1,23,26,5,2]
var b = {num:1,str:'gggg'}
function forEach (obj, fn) {
var getObjectString = Object.prototype.toString;
if(getObjectString.call(obj) === '[object Array]') {
// 如果 obj 是数组
obj.forEach(function (item,index) {
fn(index,item)
})
}else if (getObjectString.call(obj) === '[object Object]'){
// 如果 obj 是{}
for (var index in obj) {
fn(index,obj[index])
}
}
return;
}
forEach(a,function (key, value){
console.log(key,value)
})
// 结果:
// 0 1
// 1 23
// 2 26
// 3 5
// 4 2
forEach(b,function (key, value){
console.log(key,value)
})
// 结果:
// num 1
// str gggg
</script>
18. DOM 是那种基本的数据结构
树
19. DOM 操作的常用 API 有哪些
- 获取 DOM 节点,以及节点的 property 和 Attribute:
<div id="box" data-id="222"></div>
<div class="box"></div>
<div class="box"></div>
<span></span>
<span></span>
<script>
console.log(document.getElementById('box')) // 元素 <div id="box"></div>
console.log(document.getElementsByTagName('span')) // 集合
console.log(document.getElementsByClassName('.box')) // 集合
console.log(document.querySelector('#box')) // 元素
console.log(document.querySelectorAll('.box')) // 集合
// property
var obj = {a:'dsfgsdg'}
console.log(obj.a); // dsfgsdg
// 或者
console.log(document.getElementById('box').nodeType) // 1 nodeType:1 表示节点类型是元素
// Attribute
console.log(document.getElementById('box').getAttribute('data-id')) // 222
document.getElementById('box').setAttribute('data-type','dom') // 结果: <div id="box" data-id="222" data-type="dom"></div>
</script>
- 获取父节点,获取子节点
<div id="box-container">
<div id="box"></div>
</div>
<script>
console.log(document.getElementById('box').parentNode)
// <div id="box-container"><div id="box"></div></div> 获取到了父节点
console.log(document.getElementById('box-container').childNodes[0])
// #text 获取到了文本节点
console.log(document.getElementById('box-container').childNodes[1])
// <div id="box"></div> 获取到了文本节点
</script>
- 新增节点,删除节点
// 新增节点
<div id="box"></div>
<script>
//创建元素 span
var oSpan = document.createElement('span')
oSpan.innerHTML = 'span'
document.getElementById('box').appendChild(oSpan)
</script>
// 删除节点
<div id="box">
<div class="box-child"></div>
</div>
<script>
var boxChild = document.querySelector('.box-child')
// 删除子节点 .box-child
document.getElementById('box').removeChild(boxChild)
</script>
20. DOM 节点的Attribute 和 property 有何区别
- property 是一个 js 对象的属性修改
- Attribute 是对 html 标签属性的新增和修改
21. 编写一个通用的事件监听函数
<div class="box" data-name="父元素 box">
<p data-name="张三">猜猜我是谁?</p>
<p data-name="李四">猜猜我是谁?</p>
<p data-name="王五">猜猜我是谁?</p>
<p data-name="老六">猜猜我是谁?</p>
<div data-name="假七">猜猜我是谁?</div>
</div>
<script>
function bindEvent (el, type, child, fn) {
if (fn == null) {
// fn == null 等价于 fn === null || fn === undefined
// 如果没有 child 的参数
fn = child
child = null
}
el.addEventListener(type, function (e) {
if (child == null) {
// fn(e) 课程是这个写法,但是我觉得这样写,this 指向了 window,是不正确的,所以改写成了下面的
fn.call(el,e)
} else {
var ev = ev || window.event,
target = ev.target
ev.preventDefault() // 阻止默认行为
if(target.nodeName === child || target.nodeName.toLowerCase() === child) {
fn.call(target, e)
}
}
}, false)
}
var box = document.querySelector(".box")
bindEvent(box, 'click', function (e){
alert(this.getAttribute('data-name'))
})
bindEvent(box, 'click', 'p', function (e){
alert(this.getAttribute('data-name'))
})
</script>
22. 手动编写一个 ajax,不依赖第三方库
api.json
{
"name":"json"
}
<script>
var xhr = new XMLHttpRequest()
xhr.open('GET', 'http://192.168.0.14:8080/api.json', false)
xhr.setRequestHeader('Content-Type','application/json')
xhr.onreadystatechange = function (){
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText)
}
}
}
xhr.send()
</script>
移步查看更多 ajax 的具体知识点 面试知识点之 ajax 与跨域
23. window.onload 和 DOMContentLoaded
window.onload: 页面的全部资源加载完才会执行,包括图片、视频等
DOMContentLoaded: DOM 结构加载完就可以执行,此时图片、视频还没加载完
window.addEventListener('load', function (){
console.log('load')
})
window.addEventListener('DOMContentLoaded', function (){
console.log('DOMContentLoaded')
})
// 结果:
// DOMContentLoaded
// load
jquery zepto 等一般使用 DOMContentLoaded
以上为学习笔记,参考资料来源:慕课网的课程
网友评论