变量类型和计算 强制类型转换 字符串拼接 `100 + '1' = '101'`
==运算符 1 2 3 100 == '100' // true 0 == '' // true null == undefined // true
if语句 1 2 3 4 5 6 7 8 9 10 11 12 var a = true if (a) { //执行 } var b = 100 if (b) { //执行 } var c = '' if(c) { //不执行 }
逻辑运算符 1 2 3 console.log(10 && 0) //0 console.log('' || 'abc') //'abc' console.log(window.abc)
何时使用 === 和 == 只有这种情况用==
1 2 3 4 if (obj.a == null) { // 这里相当于 obj.a === null || obj.a === undefined, 简写形式 // 这是jquery源码推荐的写法 }
原型和原型链 1 2 3 4 5 6 var obj = {}; obj.a = 100; var arr = []; arr.a = 100; function fn () {}; fn.a = 100; console.log(obj.__proto__ === Object.prototype) // true
obj的隐式原型 指向 Object的显式原型,因为obj从Object继承而来
遍历对象忽略原型 1 2 3 4 5 6 7 8 var item for (item in f) { // 高游览器已经在for in 中屏蔽了来自原型的属性 // 但是这里建议还是加上这个判断,保证程序的健壮性 if (f.hasOwnProperty(item)) { console.log(item) } }
intanceof instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
1 2 3 4 5 6 7 8 9 10 11 12 function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const auto = new Car('Honda', 'Accord', 1998); console.log(auto instanceof Car); // expected output: true console.log(auto instanceof Object); // expected output: true
原型链例子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 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) return this } var div1 = new Elem('detail-page');
执行上下文 1 2 3 4 5 6 7 8 9 console.log(a) var a = 100 fn('zhangsan') function fn(name) { age = 20 console.log(name, age) var age }
范围: 一段<script>
或者一个函数
全局: 变量定义,函数声明
函数: 变量定义,函数申明,this,arguments ps: 注意’函数声明’和’函数表达式’的区别
this 先搞明白一个很重要的概念 ———— this
的值是在执行的时候才能确认,定义的时候不能确认! 为什么呢 ———— 因为this
是执行上下文环境的一部分,而执行上下文需要在代码执行之前确定,而不是定义的时候。看如下例子
1 2 3 4 5 6 7 8 9 10 var a = { name: 'A' , fn: function ( ) { console .log(this .name) } } a.fn() a.fn.call({name : 'B' }) var fn1 = a.fnfn1()
this
执行会有不同,主要集中在这几个场景中
作为构造函数执行
作为对象属性执行
作为普通函数执行
用于call
apply
bind
前两种情况咱们之前都介绍过了,这里只是统一的提出来,汇总一下,不再详细讲了。这里主要说第三种
1 2 3 4 5 function fn ( ) { console .log(this ) } fn() fn.call({a :100 })
作用域和闭包
自由变量
作用域链,即自由变量的查找
闭包的两个场景
作用域 作为有 JS 基础的同学,你应该了解 JS 没有块级作用域。例如
1 2 3 4 if (true ) { var name = 'zhangsan' } console .log(name)
从上面的例子可以体会到作用域的概念,作用域就是一个独立的地盘,让变量不会外泄、暴露出去。上面的name
就被暴露出去了,因此,JS 没有块级作用域,只有全局作用域和函数作用域 。
1 2 3 4 5 6 7 var a = 100 function fn ( ) { var a = 200 console .log('fn' , a) } console .log('global' , a)fn()
全局作用域就是最外层的作用域,如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么他们就全部都在全局作用域中。这样的坏处就是很容易装车。
1 2 3 4 5 var data = {a :100 }var data = {x :true }
这就是为何 jquery zepto 等库的源码,所有的代码都会放在(function(){....})()
中。因为放在里面的所有变量,都不会被外泄和暴露,不会污染到外面,不会对其他的库或者 JS 脚本造成影响。这是函数作用域的一个体现。
作用域链 首先认识一下什么叫做自由变量 。如下代码中,console.log(a)
要得到a
变量,但是在当前的作用域中没有定义a
(可对比一下b
)。当前作用域没有定义的变量,这成为自由变量 。自由变量如何得到 ———— 向父级作用域寻找。
1 2 3 4 5 6 7 var a = 100 function fn ( ) { var b = 200 console .log(a) console .log(b) } fn()
如果父级也没呢?再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链 。
1 2 3 4 5 6 7 8 9 10 11 12 var a = 100 function F1 ( ) { var b = 200 function F2 ( ) { var c = 300 console .log(a) console .log(b) console .log(c) } F2() } F1()
闭包 直接看一个例子
1 2 3 4 5 6 7 8 9 function F1 ( ) { var a = 100 return function ( ) { console .log(a) } } var f1 = F1()var a = 200 f1()
自由变量将从作用域链中去寻找,但是依据的是函数定义时的作用域链,而不是函数执行时 ,以上这个例子就是闭包。闭包主要有两个应用场景:
函数作为返回值,上面的例子就是
函数作为参数传递,看以下例子
1 2 3 4 5 6 7 8 9 10 11 12 function F1 ( ) { var a = 100 return function ( ) { console .log(a) } } function F2 (f1 ) { var a = 200 console .log(f1()) } var f1 = F1()F2(f1)
XMLHttpRequest 1 2 3 4 5 6 7 8 9 10 var xhr = new XMLHttpRequest()xhr.open("GET" ,"/api" , true ) xhr.onreadystatechange = function ( ) { if (xhr.readyState == 4 ) { if (xhr.status == 200 ) { alert(xhr.responseText) } } } xhr.send(null )
跨域 1 2 3 4 5 6 7 response.setHeader("Access-Control-Allow-Origin" ,"http://a.com, http://b.com" ); response.setHeader("Access-Control-Allow-Headers" ,"X-Requested-With" ); response.setHeader("Access-Control-Allow-Methods" ,"PUT,POST,GET,DELETE,OPTIONS" ); response.setHeader("Access-Control-Allow-Credentials" , "true" );