• js学习笔记之自调用函数、闭包、原型链


     自调用函数
    var name = 'world!';
        // console.log(typeof name)
        (function () {
            console.log(this.name, name, typeof name, typeof name === undefined)
            if(typeof name === undefined){
                var name = 'a!'
                console.log('hello ' + name)
            } else{
                var name = 'b!'
                console.log('hello ' + name)
            }
        })();

    运行结果是
    "world!" undefined "undefined" false
    hello b!

    这里有两个陷阱
    第一个是变量提升后 name 值为 undefined
    第二个是 typeof name 为字符串 "undefined" 
     
    闭包
    闭包就是能读取其他函数内部变量的函数。
     
    优点:
    保护函数内的变量安全,加强了封装性
    在内存中维持一个变量(用的太多就变成了缺点,占内存)
     
    缺点:
    闭包有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生
    var counter = 2
    var add = (function () {
        console.log(this.counter, counter, 'bbb') // 2, undefined, 'bbb'
        var counter = 3;
        return function () {
            counter += 1;
            console.log(counter)
        }
    })();
    add(); // 4
    add(); // 5
    add(); // 6
    console.log(counter, 'aaa') // 2, 'aaa'
     

    原型链
    所有对象的 __proto__ 都指向其构造器的 prototype
    所有函数对象的 __proto__ 都指向 Function.prototype,它是一个空函数(Empty function)
    Object.prototype.__proto__ === null

    function fn() {
            this.a = 10
            this.b = function () {
               console.log(this.a)
            }
        }
        fn.prototype = {
            b: function () {
                this.a = 20
                console.log(this.a)
            },
            c: function () {
                this.a = 30
                console.log(this.a)
            }
        }
        var myfn = new fn();
        console.log(myfn) //对象属性有a,b;原型链继承属性有b,c
    console.log(myfn.__proto__ === fn.prototype) // true
    console.log(myfn.__proto__ === myfn.constructor.prototype) // false
    myfn.b() //10 
    myfn.c() //30
    myfn.b() //30
    解析
    myfn对象第一次调用b方法,由于原型链上的b方法被覆盖,所以始终调用自身的b方法,所以就输出初始值10
    myfn调用c方法等于是调用继承的c方法,所以a属性被重新赋值,于是输出30
    myfn第二次调用b方法,由于a属性已经被c方法重新赋值,所以继续输出30

    myfn.__proto__始终指向构造器fn的prototype属性
    但是myfn.__proto__不再指向myfn.constructor.prototype

    myfn本身没有constructor属性,于是指向fn.prototype.constructor属性,
    而fn.prototype.constructor本来应该指向其自身,但是因为重新赋值fn.prototype对象,所以fn.prototype的构造函数变成了Object

    引用指针

    var a = {n:1}; 
    var b = a;  
    a.x = a = {n:2}; 
    console.log(a.x); // undefined 
    console.log(b.x); // {n:2} 

    解释
    这里的连续赋值运算顺序是先进行'.'运算符赋值,这时将a.x还是指向对象A的,
    接下来开始从右向左赋值,改变a的指向为对象B
    接下来开始a.x的赋值为对象B,这时候'.'运算符已经最先赋值了,所以还是给对象A的x属性赋值
  • 相关阅读:
    Nginx+Tomcat 集群部署
    Android5.0新特性——CardView 使用
    Android-SQLite版本问题
    Android UI ListView的使用
    Android
    Android四大组件之Activity一(组件的概念、Intent、监听)
    JAVA内部类使用
    Android 第一个程序 及 环境搭配
    Android-AsyncTask异步任务(获取手机联系人)
    Android-Application
  • 原文地址:https://www.cnblogs.com/nightstarsky/p/9182756.html
Copyright © 2020-2023  润新知