Part1 元素,元素属性,CSS属性

元素获取方法:

1. 原生DOM方法:

	document.getElementById("id");
	document.getElementsByTagName("tags");
	document.getElementsByClassName("class");

2. JQuery方法:

	$("#id")
	$("tags")
	$(".class")

JQuery优点:

  1. JQuery代码较短提高效率。并且选择对象只需要像css选择器一样即可
  2. 原生DOM没有对应元素节点时会抛出错误,JQuery则不会

元素属性方法:

1. 原生DOM方法:

	var object = document.getElementById("div");	// 获取id为div的元素节点

	object.getAttribute("id");			// 获取object的id属性
	object.setAttribute("title","123");		// 设置属性title

2. JQuery方法:

	$("#div").attr("id");				// 获取id为div的元素节点的id属性
	$("#div").attr("title","123");			// 设置属性title
	$("#div").attr({
		src = "div.png",
		alt = "a picture"
	})						// 可以设置多个属性
	$("a").attr("href",function(){...});		// 可以通过函数批量处理

	$("a").removeAttr("href");			// 删除所有a节点的href属性

JQuery优点:

比原生方法简洁,并且增加了部分方法,如:可使用函数,可以删除属性


CSS方法:

1. 原生DOM方法:

	//只能获取元素的style属性
	var object = document.getElementById("div");
	object.style.border = "1px solid black";		// 设置css属性
	Object.style.border 					// 获取Object的border属性

	//getComputedStyle方法能获得最终css属性值

	pro = window.getComputedStyle(object,null);		// 参数为("元素","伪类")
	console.log(pro.border);

2. JQuery方法:

	$("#div").css("border","1px solid black");	
	$("#div").css("border");				// 获取div的boder属性

设置css属性值原生方法和JQuery都是简单的设置元素的style属性


Part2 修改文档结构

插入和替换元素:

1. 原生DOM方法:

	var object = document.getElementById("div");
	var ins = document.createTextNode("xxxx");
	var ins1 = document.createElement("p");
	object.appendChild(ins);
	ins.appendChild(ins1);

2. JQuery方法:

	$("#div").append("<span>123<span>"); 		// 在#div元素内容末尾追加内容
	$("#div").prepend("123");			// 在#div元素内容起始处添加内容
	$("#div").before("123");			// 在#div元素之前添加内容
	$("#div").after("123");				// 在#div元素之后添加内容
	$("h2").replaceWith("<h3>");			// 将h2元素替换为h3,这里会替换成<h3></h3>,内容会消失

	//另一种方法
	$("<span>123<span>").appendTo("#div")
	$(document.createTextNode("123")).prependTo("#div");
	$("123").insertBefore("#div");
	$("123").insertAfter("#div");
	$("<h3>").replaceAll("#div");

	//复制元素
	$("#div").clone().appendTo("h3");		// 在每个<h3>内容末尾处追加元素#div

	//包装元素
	$("h1").wrap(document.createElement("div"));	// 生成<div><h1>....</h1></div>
	$("h2").wrapInner("<i></i>");			// 生成<h2><i>...</i></h2>
	$("img").wrapAll(document.createElement("div")) // 生成<div><img>...</img></div>

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