JS的变量 原型与原型链 作用域 闭包

js中的变量类型(按存储方式区分)

  1. 值类型
  2. 引用类型(指针):数组、函数、对象
    //共享内存,数据改变存在联动性。
    //可以随意的扩展属性

在javascript中,判断数据类型主要依赖下面两种方式:

  1. 如果值应为一个引用类型,使用 instanceof 操作符检查其构造函数;
  2. 如果值应为一个基本类型,使用 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 成为隐式原型
//
原型是一个对象,其他对象可以通过它实现属性继承。
image
image
image
原型链:
所有的引用类型(数组,对象,函数), __proto__属性(隐式原型)指向它的构造函数的“prototype”属性值(显式原型)


执行上下文

在代码执行之前,先执行(解析)变量定义和函数声明。

范围:一段<script>或者一个函数之内都会生成一个上下文
全局:变量定义,函数声明.执行之前,一段<script>会生成全局上下文
函数:变量定义,函数声明,this,arguments.函数执行之前会生成函数上下文

函数声明

function fn(name) {
    ...
}

函数表达式

var func = function () {
    ...
}

this

this要在执行时才能确认值,定义时无法确认

使用场景

  1. 作为构造函数执行
  2. 作为对象属性执行
  3. 作为普通函数执行

作用域链

函数的父级作用域是函数定义时候的作用域,不是函数执行时候的作用域,也就是说那个作用域定义了这个函数,这个函数的父级作用域就是谁,跟函数执行没有关系,函数自由变量要到父级作用域中找,就形成了作用域链

扫描二维码关注公众号,回复: 4366034 查看本文章

闭包

闭包使用场景

  1. 函数作为返回值
  2. 函数作为参数传递
    (函数自由变量要到父级作用域(定义时的作用域)中找)

闭包在实际中的应用

在函数外无法修改函数内的值

    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作为参数
    }

猜你喜欢

转载自blog.csdn.net/wantingtr/article/details/84099470