JavaScript闭包20171229

一 变量作用域

  • 2种作用域:全局&局部;
  • js链式作用域结构,函数内部可以直接读取全局变量;函数外部无法读取函数内的局部变量;
  • 函数内部声明变量,要用var,如果不用var,直接n=3,实际上是声明了一个全局变量;

二 如何从外部读取局部变量

  • 在函数A的内部,再定义一个函数B,函数B就可以引用函数A的局部变量(这有点像偷换概念啊。。)
function A(){
    var n=3;
    function B(){
        console.log(n);
    }
}
  • 既然B()可以读取A()中的局部变量,那么重要把B()作为返回值,就可以在A()外部,读取A的内部变量了;
function A(){
    var n = 3;
    function B(){
        console.log(n);
    }
    return B;
}
var re = A();
re();//3

三 闭包的概念

  • 上述,B函数,就是闭包;
  • 一个理解:闭包是 能够读取其他函数内部变量的 函数;——把函数内部和函数外部连接起来的一座桥梁;
  • 在JavaScript中,对于函数A,只有函数A内部的子函数(比如取名叫B)才能读取函数A内的局部变量(其实是函数B的外部变量);——简单理解:定义在一个函数内部的函数;

四 闭包用途-2个

  • 读取函数内部的变量;
  • 让这些变量的值始终保持在内存中;
    re,就是返回的闭包f2函数,一共运行了2次:第一次的值0,第二次的值1;这表示,函数f1中的局部变量n一直保持在内存中,没有在f1调用后自动清除;

    function f1(){
        var n=0;
        nAdd = function(){n+=1;}
        // 1 nAdd前面没有var,所以它是一个全局变量;
        // 2 nAdd的值,是一个匿名函数,这个匿名函数本身也是一个闭包----nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作;
        function f2(){
            console.log(n);
        }
        return f2;
    }
    var re = f1();
    re();//0
    nAdd();
    re();//1
    
    var name = "我的window";
    var object = {
        name:"my object",
        getNameFunc:function(){
            return function(){
                return this.name;
            };
        }
    };
    object.getNameFunc()()//"我的window"
    
    var name = "我的window";
    var object = {
        name:"my object",
        getNameFunc:function(){
            var that = this;
            return function(){
                return that.name;
            }
    
        }
    };
    object.getNameFunc()();//"my object"
    

python-notes

一 基础

1.1 安装

  • 安装完成后,命令行输入python,显示版本信息,安装并加入环境变量成功;安装官方下载的python,自动装上了解释器Cpython;
  • 交互模式 & 命令行模式
交互模式输入一行,执行一行,用来初学者调试学习,不是python真正的运行环境;

1.2 test-python

  • 换行格式:''' '''
print('''line1
line2
line3''')
  • 格式化字符
#这是注释
name=input('请输入你的名字:')
a=int(input('去年的成绩:'))
b=int(input('今年的成绩:'))
c=(b-a)/a*100
d=(a-b)/a*100
if a<b:
    print('%s 今年的成绩提升了:%.2f%%' % (name,c))
elif a>b:
    print('%s 今年的成绩下降了:%.2f%%' % (name,d))
else:
    print('%s 今年的成绩与去年持平' % name)

#下面这种是用format
>>> 'Hello, {0}, 成绩提升了 {1:.1f}%'.format('小明', 17.125)
'Hello, 小明, 成绩提升了 17.1%'
  • 条件
name=input('请输入你的名字:')
a=int(input('输入身高,单位是cm:'))
b=int(input('输入体重,单位是kg:'))
bmi = b/(a*a/10000);
if bmi>32:
    print('严重肥胖')
elif bmi>28:
    print('肥胖')
elif bmi>25:
    print('过重')
elif bmi>18.5:
    print('正常')
else:
    print('过轻')
  • 循环,注意:不要滥用break和continue,会造成代码执行逻辑分叉过多,容易出错;可以通过改写循环条件或者修改循环逻辑
# for in
sum = 0
for x in range(101):
    sum = sum+x
print(sum)
# while
sum = 0
n = 99
while n>0:
    sum = sum+n
    n = n-2
print(sum)
# break
n = 1
while n <= 100:
    if n > 10: # 当n = 11时,条件满足,执行break语句
        break # break语句会结束当前循环
    print(n)
    n = n + 1
print('END')
# continue
n = 0
while n < 10:
    n = n+1
    if n%2==1:
        continue
    print(n)
  • range
# 计算任意两个整数之间所有数字的和
sum = 0
num1 = int(input('请输入第一个整数:'))
num2 = int(input('请输入第二个整数:'))
min=0
max=0
if num1>num2:
    min=num2
    max=num1
elif num1<num2:
    min=num1
    max=num2
else:
    min=num1
    max=num1
for x in range(min,max+1):
    sum=sum+x
print('这两个数之间所有整数的和为:%d' % sum)

1.3 语法基础

  • 数据类型:整数;浮点数;字符串;布尔值;空值;变量;常量
>>> 10 // 3
3
>>> 10 / 3
3.3333333333333335
  • python-动态语言:变量类型不固定;
a = 123 # a是整数
print(a)
a = 'ABC' # a变为字符串
print(a)
  • 字符串的编码问题:ASCII,GB2312,Unicode,UTF-8;注意:如果没有特殊要求,牢记使用UTF-8;
1、ASCII(1个字节) : 
8个比特bit 1个字节byte;
一个字节能表示的最大整数255;
最早只有127个字符编码--ASCII编码;
要处理中文,至少要2个字节,而且还不能和ASCII编码冲突,
所以,中国制定了GB2312编码;
2、GB2312;
但各国有各国的标准了,
比如日文Shift_JIS,韩文Euc-kr;
多语言混合的文本里,不可避免会冲突,乱码;
3、Unicode:所以有了Unicode,它把所有语言都统一到一套编码里;
Unicode(2个字节)最常用的是两个字节标识一个字符;
统一成Unicode,乱码问题是解决了,
但是如果文本基本上是英文的话,
用Unicode编码比ASCII编码需要多一倍的存储空间;
所以,出现了把Unicode编码转化为“可变长编码”的UTF-8编码;
4、UTF-8:把一个Unicode字符根据不同的数字大小编码成1-6个字节,
常用的英文字母被编码成1个字节,汉字通常是3个字节,
很生僻的字符才会4-6个字节;
并且,ASCII编码可以被看成是UTF-8编码的一部分,
所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作;

python的2种内置数据类型:list(列表)和tuple(元组)

  • list-有序集合;list里面元素的数据类型可以不同;list元素可以使另一个list
classmates = ['Michael', 'Bob', 'Tracy']
len(classmates)
classmates[2]
#索引2'Tracy'
classmates[-1]
#倒数第一个'Tracy'
classmates[-2]
#倒数第二个'Bob'
#添加到末尾,或插入到指定位置
classmates.append('Adam')
classmates.insert(1, 'Jack')
#['Michael', 'Jack', 'Bob', 'Tracy', 'Adam']
#删除末尾,或删除指定位置
classmates.pop()
#'Adam'
classmates.pop(1)
#'Jack'
#替换元素
classmates[1]='Sarah'
#['Michael', 'Sarah', 'Tracy']

  • tuple-一旦初始化就不能修改;因为不可变,代码更安全;能用tuple代替list就尽量用tuple;
#注意:定义只有一个元素的tuple时,【必须】加一个逗号,,来消除歧义(()括号可以表示数学公式中的小括号,python规定,按小括号计算,结果变成了一个数)
t = (1,)
#python在显示只有1个元素的tuple时,也会加一个逗号,以免误解;

# 来看一个“可变的”tuple
t = ('a', 'b', ['A', 'B'])
t[2][0] = 'X'
t[2][1] = 'Y'
t
('a', 'b', ['X', 'Y'])
# 表面上,tuple好像变了,但其实变的不是tuple的元素,而是list的元素;
# tuple一开始指向的list并没有改;
# tuple的每个元素,指向永远不变;
# 指向'a',就不能指向'b',指向一个list,就不能改成指向其他对象,但指向的这个list本身是可变的;
# 要确保tuple不能改变,要保证tuple的每一个元素本身也不能变;

dict和set

  • dict, python内置的字典,在其他语言中称为map,使用键-值(key-value)存储,极快的查找速度;在存进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value;
  • 注意:dict内部存放的顺序和key放入的顺序没有关系
  • a.查找和插入的速度极快,不会随着key的增加而变慢;b.需要占用大量的内存,内存浪费多
  • dict的key必须是 不可变对象
  • 通过key计算位置的算法,叫做hash哈希算法;python中,字符串、整数都不可变,可以作为key,list是可变的,不能作为key
d={'michael':98,'bob':85,'tracy':93}
print(d['michael'])
'thomas' in d
False
d.get('thomas',-1)
# 如果key不存在,返回自己指定的value
-1

d.pop('bob')#删除一个key
85
  • set ,是一组key的集合,但不存储value,里面的key不能重复
s = set([1,2,3,3,4,4,5])
s
{1,2,3,4,5}
s.add(8)
s
{1,2,3,4,5,8}
s.remove(3)
s
{1,2,4,5,8}
# set可以做交集、并集
s1=set([1,2,3])
s2=set([2,3,4])
s1&s2
{2,3}
s1|s2
{1,2,3,4}
  • 不可变对象
# list内容是会变化的,比如
a=['c','b','a']
a.sort()
a
['a','b','c']
# str不可变
a = 'abc'
b = a.replace('a','A')
'Abc'
a
'abc'#没有变化

# a是变量,'abc'才是字符串对象;a本身是一个变量,它指向的对象的内容是'abc';
# replace创建了一个新的字符串'Abc'并返回
# 变量a仍指向字符串'abc',但变量b却指向新字符串'Abc'了