Part1 等号、不等运算符

  • ”==”和”===” 都可以用来判断相等,其中”===”用来检测严格相等,”==”判断相等可以进行类型转换
  • ”!=”和”!==”为不等,同上

Try:


	"1" == 1				// true
	"1" === 1				// false,类型不等
	{} == {}				// 任何对象都不相等
	NaN !== NaN				// true
	0 === -0 				// true
	null == undefined			// true, (上一节Part3)
	null === undefined			// false

关于null和undefined

  • ”===”运算符 —
    1. 首先判断类型,类型不相等返回false
    2. 其次判断值
  • ”==” 运算符
    1. 如果严格相等则必然相等
    2. 如果一个值是数字一个是字符串,将字符串转换为数字后比较
    3. 如果是布尔值,先转换为数字后比较
    4. 如果一个值是对象,先将对象转换为原始值

Part2 in,instanceof运算符

直接上栗子

Try:


	var person = {name:"jack",sex:"male"};

	"name" in person 		// true
	"age"  in person		// false
	"toString" in person	// true

	var data = [1,2,3];
	"0" in data 			// true
	3   in data 			// false

	var a = function(){};
	var cas = new a();
	cas instanceof a		// true
	cas instanceof Array	// false

	/*判断a.prototype是否在cas的原型链上,a.prototype == cas.__proto__*/

  • in 左操作符为字符串或可转为字符串的值,有操作符为一个对象
  • instanceof 左操作符为一个对象,右操作符为一个类 eg. 表达式o instanceof f ,首先计算f.prototype,然后在o的原型链中查找o, 如若找到则返回true,反之返回false。(此处权威指南p78,“在原型链中查找o不太准确”)

  • 原型链,var cas = new a(); =>
    1. var cas={}; cas.__proto__ = a.prototype; a.call(cas);
    2. a.__proto = Function.prototype
    3. Function.__proto__ = Object.prototype 后面的章节详细介绍

Part3 eval

eg. eval(“3+2”) // 5 eval(),只有一个参数,参数为字符串时进行编译,不是字符串直接返回这个参数

Try:

	
	var geval = eval;
	var x="global",y="global";
	function f(){
	    var x = "local";
	    eval("x += 'changed'");
	    return x;
	}

	function g(){
	    var y = "local";
	    geval("y += 'changed'");
	    return y;
	}
	console.log(f(),x);		//localchanged global
	console.log(g(),y);		//local globalchanged

当通过别名调用,eval会将字符串当成顶层全局代码执行(ES5), 直接调用和普通函数一样

Part4 void运算符

  • 返回undefined,eg. void(5) // undefined
  • 还可以这样使用

    void function(){}(); => 效果等同于 (function(){}()); 可以将void 替换成其他运算符

  • 在Html标签a中使用 javascript:void

Part1 JS特殊值

javascript中特殊的值:NaN(非数字值), Infinity(上溢出), -Infinity(下溢出)

Try:

	0/0  ===   NaN		// false
	isNaN(0/0)			// true
	1/0  ===  Infinity  // true
	-1/0 === -Infinity  // true
	isFinity(1/0) 		// true
	1/0 === -1/0		// false

Part2 浮点数误差

javascript采用IEEE-754,是一种二进制表示法 ,所以表示十进制的时候会有误差…

Try:

	137.3 - 40 === 97.3 	// false
	137.3 - 40 				// 97.30000000000001
	0.3 - 0.2 === 0.2 -0.1 	// false

解决方法,四舍五入

	var precise = 13;
	return Math.round(num*Math.pow(10,precise))/Math.pow(10,precise);

当precise>14又会发生误差,所以只要将浮点数转换至整数后再做运算就不会出现误差

Try:


	(137.3*10 - 40*10)/10 === 97.3 		// true

	function sub(a,b){
		var c = a.toString(), d = b.toString();
		var alength,blength;
		if(c.indexOf(".") > -1)
			alength = c.length - c.indexOf(".") - 1;
		else
			alength = 0;

		if(d.indexOf(".") > -1)
			blength = d.length - d.indexOf(".") - 1;
		else
			blength = 0;

		var precise = Math.pow(10,Math.max(alength,blength));
		return (a*precise - b*precise)/precise;
	}
	sub(137.3,40) //97.3

	... same way to implement add ..

part3 null和undefined

null是一个特殊值,描述“空值”, typeof(null) => “object”,null是一个特殊的对象 undefined也用来表示“空值”,当变量未初始化、函数无返回的时候都会得到一个undefined值


	null == undefined 	// true
	nul === undefined 	// false

part4 类型转换

参考《javascript权威指南》p49 表3-2. undefined, null, 0, -0, NaN, “0”转换为Boolean是都为false , 其他值都为true(包括±Infinity)

特别注意:


	Number(undefined) 			// NaN
	Number(null) 				// 0
	Number([8]) 				// 8
	Number(["a"]) 				// NaN
	Number("h")					// NaN
	String([8]) 				// "8"
	String([2,3]) 				// "2,3"
	Object(undefined) 			// throws TypeError
	Object(null) 	 			// throws TypeError


对象转换:


	//调用toString()方法,在原型链上查找到Object.toString()方法
	String({}}) 			// [object Object]

	//调用valueOf(),没有该方法,调用toString再字符串其转换为数字
	Number({}) 			// NaN

	//数组转换为数字
	Number([2,3]) -> valueOf in [2,3] // false 
	-> [2,3].toString() // "2,3" 
	-> Number("2,3")	//NaN

  1. ”+”操作当有一个操作符为对象会执行上述操作
  2. ”=”,”+”操作,除Date类型外的对象会进行对象到数字的转换,Date类型转换为String

part5 变量作用域

c++中变量作用域为“块级作用域”,{}中每一段代码有各自的作用域 JS中的作用域为“函数作用域”,函数内声明的所有变量在函数体内始终可见


	var now = new Date();
	(function scope(){
	    console.log(now);	// undefined
	    var now = 11;
	    console.log(now);	// 11
	}());					

  1. 第一个console.log打印now的值,此时now虽然声明但还未赋值为undefined
  2. 第二个赋值为11,打印11

环境:Qt5.4QtCreator, mysql 5.7.18

解决方案

  • 1.首先保证Qt和mysql的位数相同,假如Qt是32位的那么mysql也需要32位的

  • 2.mysql安装的路径要没有空格

  • 3.将mysql安装路径下,\lib目录下的libmysql.dll拷贝至…\Qt5.4.0\5.4\mingw491_32\bin目录下即可

Python装饰器

装饰器


装饰器是为函数和类指定管理代码的一种方式.

  • 函数装饰器在函数定义的时候进行名称重绑定,提供一个逻辑层来管理函数和方法 或随后对它们的调用。
  • 类装饰器在类定义的时候进行名称重绑定,提供一个逻辑层来管理类,或管理随后 调用它们所创建的示例。

  • 函数装饰器安装包装器对象,以在需要的时候拦截随后的函数调用并处理它们。

  • 类装饰器安装包装器对象,以在需要的时候拦截随后的实例创建调用并处理它们。

  • 总之就是提供一个逻辑层来控制类或者函数,拦截原函数和原实例对他们进行再加工,可以在不修改原函数和原类的基础上再加工函数和类的方法

装饰器优点:

  • 装饰器有一种非常明确的语法,这使得它们比那些可能任意地远离主体函数或类的 辅助函数调用更容易为人们发现。

  • 当主体函数或类定义的时候,装饰器应用一次;在对类或函数的每次调用的时候, 不必添加额外的代码。

  • 由于前面两点,装饰器使得一个API的用户不太可能忘记根据API需求扩展一个函 数或类。

  • 简单的来说就是减少冗余

调用方式:

def decorator:
    ....

class decorator:
    ....

函数装饰器:


@decorator # Decorate function
def F(arg):
    ...
F(99) # Call function

# equal to

def F():
    ...

F = decorator(F)

此处调用F的结果就是调用 decorator(F)(…) (decorator(F)此处为一个函数),

更为详细的调用:

def decorator(F): # On @ decoration
    def wrapper(*args): # On wrapped function call
        # Use F and args
        # F(*args) calls original function
    return wrapper

@decorator # func = decorator(func)
def func(x, y): # func is passed to decorator's F
    ...

func(6, 7) # 6, 7 are passed to wrapper's *args

在类成员函数中使用:

class decorator:
def __init__(self, func): # On @ decoration
    self.func = func

def __call__(self, *args): # On wrapped function call
    self.func(*args)
    print(*args)

@decorator
def func(x, y): # func = decorator(func)
    print("func")

func(6, 7) # 6, 7 are passed to __call__'s *args

##result:
func
6 7

此时调用func(6,7)实际是调用decorator.call(func,(6,7)) 稍作修改:

	class decorator:
	    def __init__(self, func): # func is method without instance
	        print("init",func)
	        self.func = func
	    
	    def __call__(self, *args): # self is decorator instance
	        print("call",*args)
	        self.func(*args)

	class C:
	    @decorator
	    def method(self, x, y): # method = decorator(method)
	        print("method",x,y)# Rebound to decorator instance

	x =C()
	x.method(C,1,2)

	##reusult:

    init <function C.method at 0x0000000000A612F0>
	call <class '__main__.C'> 1 2
	method 1 2

仍然遵循F = decorator(F),即decorator(method)(C,1,2) => call(method,(C,1,2)) => C.method(C,1,2) 但是这里有个问题,当调用x.method(1,2)时,最终调用的是C.method(1,2),此时会少一个参数C类的”self”参数,所以还要传一次”C”进去

	def decorator(F): 
	    def wrapper(*args):
	        return F(*args)
	    return wrapper

	@decorator
	def func(x, y): # func = decorator(func)
	    print(x,y)

	func(6, 7)

	class C:
	    @decorator
	    def method(self, x, y):
	        print("method",x,y)

	X = C()
	X.method(6, 7)

	#result
	6 7
	method 6 7

这里使用嵌套函数装饰器显然比刚才的例子要好,这也是装饰器比较普遍使用的方法。

类装饰器


	@decorator # Decorate class
	class C:
	    ...

	x = C(99) # Make an instance

	#equal to

	class C:
	    ...

	C = decorator(C) # Rebind class name to decorator result
	x = C(99) # Essentially calls decorator(C)(99)

和函数装饰器基本一致,只不过是换成的类而已。例子:

	def decorator(cls): # On @ decoration
	    class Wrapper:
	        def __init__(self, *args): # On instance creation
	            print(*args)
	            self.wrapped = cls(*args)

	        def __getattr__(self, name): # On attribute fetch
	            return getattr(self.wrapped, name)
	    return Wrapper

	@decorator
	class C: # C = decorator(C)
	    def __init__(self, x, y): # Run by Wrapper.__init__
	        self.attr = 'spam'

	x = C(6, 7) # Really calls Wrapper(6, 7)
	print(x.attr) # Runs Wrapper.__getattr__, prints "spam"

	##result:

	6 7
	spam

此处装饰器 C = decorator(C), decorator返回Wrapper,所以调用C其实是调用Wrapper 再看下面的例子:

	class Decorator:
	    def __init__(self, C): # On @ decoration
	        self.C = C
	    def __call__(self, *args): # On instance creation
	        print("call")
	        self.wrapped = self.C(*args)
	        return self
	    def __getattr__(self, attrname): # On atrribute fetch
	        return getattr(self.wrapped, attrname)

	@Decorator
	class C:
	    def __init__(self,*args):
	        self.happy= args

	x = C(12)  # x = Decorator(C)(12)
	print(x.__getattr__("happy"),x)
	y = C(436) # Overwrites x!
	print(x.__getattr__("happy"),y.__getattr__("happy"),y)

	##result
	call
	(12,) <__main__.Decorator object at 0x00000000008145C0>
	call
	(436,) (436,) <__main__.Decorator object at 0x00000000008145C0>

实例x,y指向的地址其实是一样的,所以第二次初始化y的时候会重写x

装饰器嵌套


有的时候,一个装饰器不够。为了支持多步骤的扩展,装饰器语法允许我们向一个装饰的函数或方法添加包装器逻辑的多个层。当使用这一功能的时候,每个装饰器必须出现在自己的一行中。这种形式的装饰器语法:

	@DecoratorA
	@DecoratorB
	@DecoratorC
	def C():
	    pass


	#equal to

	C = DecoratorA(DecoratorB(DecoratorC(C)))

装饰器参数


	@Decorator(A, B)
	def F(arg):
	...
	F(99)

	#equal to

	F = Decorator(A,B)(F)

	F(99) # Decorator(A,B)(F)(99)

例如:

	def Decorator(x,y):
	    print(x,y)
	    def Myfuc(func):
	        return func
	    return Myfuc


	@Decorator(1, 2)
	def F(arg):
	    print(arg)

	F(99) # equal to Decorator(1,2)(F)(99) => Myfunc(F)(99) => func(99)

	##result
	1 2
	99

1.Jekyll是什么?##

Jekyll 可以简单的生成静态博客站点。它有一个模版目录,其中包含原始文本格式的文档,通过 Markdown (或者 Textile) 以及 Liquid 转化成一个完整的可发布的静态网站。Jekyll 也可以运行在 GitHub 上,也就是说,你可以使用 GitHub 的服务来搭建你的项目页面、博客或者网站。

2.准备工作

下载安装之后,终端输入,即可安装Jeyll:

gem install jekyll

(官方文档并不建议你在 Windows 平台上安装 Jekyll, 但是不妨碍安装使用。),windows可以在wsl2中使用。

3.使用Jekyll

这里我们下载喜欢的Jekyll模板之后解压到目录,之后使用命令:

jekyll build -s 模板项目目录 -d 要生成的目录地址
jekyll s --watch  模板项目目录 -d 要生成的目录地址

然后就可以在本地看到效果。在本地调试十分适合这样子做。 下面是Jekyll的主要目录结构。

.
├── _config.yml
├── _drafts
|   ├── begin-with-the-crazy-ideas.textile
|   └── on-simplicity-in-technology.markdown
├── _includes
|   ├── footer.html
|   └── header.html
├── _layouts
|   ├── default.html
|   └── post.html
├── _posts
|   ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
|   └── 2009-04-26-barcamp-boston-4-roundup.textile
├── _site
└── index.html

使用模板的好处就是适合快速入手Jekyll。之后就是看是否需要进行模板修改和升级。

目录结构

Header1 Header2
_config.yml 保存配置数据。可以用site.xxx调用
_drafts 存放未发布文章的目录
_includes 可以包含目录调用文件 { %include xxx% }
_layouts 包裹在文章外部的模板目录。布局可以在YAML头信息中根据不同文章进行选择。
_posts 博客文章所在目录,命名格式 时间(2013-05-22)-名字.md(or .textile)
_site 生成目录,放在github中时,最好配置.gitignore中

1.安装Timezone:

gem install tzinfo
gem install tzinfo-data
同时应该向Gemfile添加 gem 'tzinfo-data'

以免出现“No source of timezone data could be found. ”

2.ssl证书问题

出现问题描述大致如下:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

3.提示”servlet.rb:3:in `require’: cannot load such file – webrick (LoadError)“

需要安装webrick
bundle add webrick

解决方法:

首先准备好数字证书cert.pem, 下载地址:

https://curl.haxx.se/ca/cacert.pem

Linux

export SSL_CERT_FILE=/usr/local/etc/openssl/certs/cert.pem

Windows

set SSL_CERT_FILE=xxxxxx\cacert.pem

refer to Stackoverflow