1、数据类型(usbno)
- 值类型(基本类型)
- Undefined(未定义)
- String(字符串)
- Boolean(布尔)
- Number(数字)
- Null(空)
- 引用数据类型
- Object(对象)
2、检测一个变量是不是NaN
- ES6:isNaN()
- ES5: a != a ,返回false不是NaN,返回true 是NaN
3、IFEE (匿名函数自执行)
function show(){
console.log('我是正常函数执行')
}
show();
(function () {
console.log('我是匿名函数自执行')
})();
- 作用:处理变量污染(防止变量覆盖)
var a = 12
var a = 13
console.log(a) //=> 13
4、closure(闭包)
什么是闭包?
闭包就是指有权访问另一个函数作用域中的变量的函数。
讲解闭包
通常,函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。
function fn1() {
var name = 'iceman';
function fn2() {
console.log(name); fn2的词法作用域能访问fn1的作用域
}
return fn2;
}
var fn3 = fn1();
fn3();
这样就清晰地展示了闭包:
- fn2的词法作用域能访问fn1的作用域
- 将fn2当做一个值返回
- fn1执行后,将fn2的引用赋值给fn3
- 执行fn3,输出了变量name
我们知道通过引用的关系,fn3就是fn2函数本身。执行fn3能正常输出name,这不就是fn2能记住并访问它所在的词法作用域,而且fn2函数的运行还是在当前词法作用域之外了。
正常来说,当fn1函数执行完毕之后,其作用域是会被销毁的,然后垃圾回收器会释放那段内存空间。而闭包却很神奇的将fn1的作用域存活了下来,fn2依然持有该作用域的引用,这个引用就是闭包。
再次解释闭包
闭包绝不仅仅是一个无用的概念,你写过的代码当中肯定有闭包的身影,比如类似如下的代码:
function waitSomeTime(msg, time) {
setTimeout(function () {
console.log(msg)
}, time);
}
waitSomeTime('hello', 1000);
定时器中有一个匿名函数,该匿名函数就有涵盖waitSomeTime函数作用域的闭包,因此当1秒之后,该匿名函数能输出msg。
另一个很经典的例子就是for循环中使用定时器延迟打印的问题:
for (var i = 1; i <= 10; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
在这段代码中,我们对其的预期是输出1~10,但却输出10次11。这是因为setTimeout中的匿名函数执行的时候,for循环都已经结束了,for循环结束的条件是i大于10,所以当然是输出10次11咯。
究其原因:i是声明在全局作用中的,定时器中的匿名函数也是执行在全局作用域中,那当然是每次都输出11了。
原因知道了,解决起来就简单了,我们可以让i在每次迭代的时候,都产生一个私有的作用域,在这个私有的作用域中保存当前i的值。
for (var i = 1; i <= 10; i++) {
(function () {
var j = i;
setTimeout(function () {
console.log(j);
}, 1000);
})();
}
这样就达到我们的预期了呀,让我们用一种比较优雅的写法改造一些,将每次迭代的i作为实参传递给自执行函数,自执行函数中用变量去接收:
for (var i = 1; i <= 10; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, 1000);
})(i);
}
更优雅的写法
for (let i = 1; i <= 10; i++) {
setTimeout(function () {
console.log(i);
}, 1000);
}
5、DOM事件流
什么是事件流
事件流描述的是从页面中接受事件的顺序。 但IE和Netscape开发团队居然提出了两个截然相反的事件流概念。
- IE的事件流是 事件冒泡流,
- 高级的浏览器 冒泡和捕获都有, 默认是冒泡,怎么变成捕获?在事件绑定的第三个参数 传个 true,如果不传,默认就是false
<div id="outer">outer
<div id="box">box
<div id="myDiv">myDiv</div>
</div>
</div>
<script>
var outer = document.getElementById('outer');
var box = document.getElementById('box');
var myDiv = document.getElementById('myDiv');
outer.addEventListener('click', function(e) {
console.log('1. outer 冒泡');
e = e || window.event; // 后一种为兼容IE的写法
var target = e.target || e.srcElement;
console.log(target); // 返回目标元素(事件源)
}, false);
box.addEventListener('click',function(e) {
console.log('2. box 冒泡');
e = e || window.event;
var target = e.target || e.srcElement; // 后一种为兼容IE的写法
console.log(target);
}, false);
myDiv.addEventListener('click', function(e) {
console.log('3. myDiv 冒泡');
e = e || window.event;
var target = e.target || e.srcElement;
console.log(target);
}, false);
</script>

事件捕获
1>2>3>4>5
事件冒泡
6>7>8>9>10
6、this的常见面试的坑和解决
-
全局 this 是 Window
-
函数 this 是 window, 如果在use strict this 是undefined
-
对象
-
严格模式
'use strict' var teacer = { name: 'hell', showName: function(){ console.log(this) // 对象本身 teacer } } teacer.showName()'use strict' var teacer2 = { name: 'hell', showName: function(){ function testThis (){ console.log(this) // undefined } testThis(); } } teacer2.showName() -
非严格模式
var name = '逍遥' var teacer2 = { name: 'hell', showName: function(){ console.log(this) // 对象本身 teacer2 function testThis (){ console.log(this) // Window console.log(this.name) // 逍遥 } testThis(); } } teacer2.showName()
-
7、call、apply、bind
- 意义: 改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向。
- call、apply与bind的差别
- call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数,并不执行。
- call、apply的区别
- call和aplly的第一个参数都是要改变上下文的对象,
- call从第二个参数开始以参数列表的形式展现,fn.call(obj, 10, 20, 30)
- apply从第二个参数开始放在一个数组里面作为它的第二个参数fn.apply(obj, [10, 20, 30])。
- 那个性能更好
- call的性能要比apply好,尤其是传递给函数参数超过三个的时候
function show(){
console.log(this) // window
}
show();
function show(){
console.log(this) // '我是不是你最疼爱的人'
}
show.call('我是不是你最疼爱的人');
8、创建对象的几种方法及继承
- 单体模式
var tracher = { name: '李瑶', age:18, showName: function(){ return this.name } }; tracher.showName(); - 原型模式
function tracher(name, age){ this.name = name; this.age = age; } tracher.prototype.showName = function(){ return this.name; }; var dabinge = new tracher('liyao', 18); dabinge.showName(); - 伪类模式
class tracher{ constructor(name, age){ this.name = name; this.age = age; } showName(){ return this.name } } var debinge = new tracher('liyao', 18); debinge.showName();