js中的变量类型(按存储方式区分)
- 值类型
- 引用类型(指针):数组、函数、对象
//共享内存,数据改变存在联动性。
//可以随意的扩展属性
在javascript中,判断数据类型主要依赖下面两种方式:
- 如果值应为一个引用类型,使用 instanceof 操作符检查其构造函数;
- 如果值应为一个基本类型,使用 typeof 检查其类型
type of 函数
typeof只能区分值类型的详细类型,无法区分引用类型,但可以区分出函数来
typeof undefined;//undefined
typeof 'abc';//string
typeof 123;//number
typeof true;//boolean
typeof {};//object
typeof [];//object
typeof null;//object
typeof console.log//function
===与==
if (obj.a == null){
// 这里相当于 obj.a === null || obj.a ===undefined ,因为 undefined == null 值为true
// 其他情况最好都用===
}
原型
对于引用类型来说
//都有__proto__属性,指向其构造函数的 prototype 属性值
//所有的函数,都有一个 prototype 属性,属性值也是一个普通的对象
//函数的 prototype 称显式原型,引用类型的 _proto 成为隐式原型
//
原型是一个对象,其他对象可以通过它实现属性继承。
原型链:
所有的引用类型(数组,对象,函数), __proto__属性(隐式原型)指向它的构造函数的“prototype”属性值(显式原型)
执行上下文
在代码执行之前,先执行(解析)变量定义和函数声明。
<mark>范围</mark>:一段<script>
或者一个函数之内都会生成一个上下文
<mark>全局</mark>:变量定义,函数声明.执行之前,一段<script>
会生成全局上下文
<mark>函数</mark>:变量定义,函数声明,this,arguments.函数执行之前会生成函数上下文
函数声明
function fn(name) {
...
}
函数表达式
var func = function () {
...
}
this
this要在执行时才能确认值,定义时无法确认
使用场景
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
作用域链
函数的父级作用域是函数定义时候的作用域,不是函数执行时候的作用域,也就是说那个作用域定义了这个函数,这个函数的父级作用域就是谁,跟函数执行没有关系,函数自由变量要到父级作用域中找,就形成了作用域链
闭包
闭包使用场景
- 函数作为返回值
- 函数作为参数传递
(函数自由变量要到父级作用域(定义时的作用域)中找)
闭包在实际中的应用
在函数外无法修改函数内的值
function isFirstLoad(){
var _list = []
return function(id) {
//函数作用域
if(_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
var firstLoad = isFirstLoad()
firstLoad(1) //true
firstLoad(1) //false
firstLoad(10) //true
firstLoad(10) //false
//对于这个程序来说,在isFirstLoad函数外面,无法修改_list的值
问题:创建10个<a>
标签,点击的时候弹出来对应的序号
错误方法
var i,a
for(i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e) {
//点击时执行
e.preventDefault()
alert(i) //自由变量,要去父作用域(全局作用域)寻找
})
document.body.appendChild(a)
在执行时,当click事件发生时,外层for循环已经执行完毕,即i已经加到10了。
所以无论点击哪个元素,弹出来的序号都是10.
正确方法
var i
for(i=0;i<10;i++) {
(function(i) {
//函数作用域
//自执行函数,不用调用,只要定义完成,就会立即执行。
var a = document.createElement('a');
a.innerHTML = i + '<br>'
a.addEventListener('click',function(e) {
e.preventDefault()
alert(i)
//改变了父级作用域
})
document.body.appendChild(a)
})(i)//相当于创建了10个函数,每个函数都带着从0-9的i作为参数
}