title | tags | notebook |
---|---|---|
编程日记_2017-5 |
编程日记 |
今天买了PHP的书,却在晚上学习起了Python,大家一直说Python是一门十分简单的语言,所以我下载了Head first Python的电子书。经过短暂的学习,发现学习Python是一个令人愉悦的事情。而且,Python和JS有很多相似之处,例如他们都是弱类型的动态语言。
Python中的数组不叫数组,叫做列表list,严格意义上说它并不等同于数组的功能。用list.append('')添加更多的项,用list.pop(),删除最后一个项,并返回,用**list.remove("itemname")移除特定的项,用list.insert(position, insertItem)在特定位置添加特定项,用list.extend(anotherList)**合并更多的list。
Python通过**isinstance(testName, datatype)来验证一个标识符指示的数据类型是否为datatype,例如测试:isinstance(arr1, list)检测arr1是否是一个列表,类似于JS中的test instanceof datatype。用len()**方法表示某个数据段的长度,类似于JS中的.length;
像instance()和print()这种方法叫做python内置函数(BIF)。
其次,Python的循环语句也更为简单,可以通过for item in list来进行一个列表内的元素遍历,item即为每一项,当然也可以使用while条件为真的时候,处理数据。
Python中的**组(suite)**表示的是代码块,其通过缩进的书写风格来表示。
Python中的函数使用def关键字声明:def functionName():
综上,Python与JS的不同之处在于,前者的条件语句以及函数等代码块中不适用花括号,直接用冒号就可以了。
Python的逻辑操作符与PHP类似,and,or,not。Python中,不同数据类型的字符串不能够直接用+连接,而是要进行转换。例如一个字符串和一个数字,"this is "+18则会报错,正确的做法是,进行数据类型的转换,"this is " \\\\\\\\+ str(18)
,还有一种方法是使用%对字符串进行格式化:
"this is %d" % 18
,用18替换%d,当然,%d替换的是整数,若要替换小数,则是%f,%s替换字符串。
Python还有一些数据类型转换的方法:int(x)
,float(x)
,bool(x)
需要注意的是,int()和float()进行转换时,要转换的值并不能转换出现非数字字符的值
Python的input()方法允许用户输入一些内容,并且将输入的内容转换为字符串。例如下面 的代码中,输入的数字会被转换为该数字的字符串形式,使得与num无法进行比较,所以需 要使用int()方法进行数据类型转换。
from random import randint
num = randint(1, 100)
print('请输入一个数字:')
answer = False
while answer == False:
inputNum = int(input('猜猜看,我想的是什么数字:'))
if inputNum < num:
print('%d太小了' % inputNum)
elif inputNum > num:
print('%d太大了' % inputNum)
else:
print('猜对了!')
answer = True
其次,在上面的代码第一行,引入了Python随机函数库,具体细节有待学习。
再者,注意上面代码中的条件判断语句的格式。
在循环中,continue表示跳过本轮循环,继续下一轮;break表示跳出循环,不再执行。
Python的函数由def关键字后面跟上标识符、括号以及冒号定义,冒号下面就是通过缩进表示函数体。
函数的调用与JS一致,在函数标识符后面加上括号即可(有参数还需要加上参数)。
函数定义的时候定义的参数叫做形参,函数调用的时候传入的参数叫做实参。
函数仍然有局部变量之说,可以使用global
关键字定义一个全局变量,不管它在什么地方定义
Python的变量查找与JS不同,在下面这个例子中,定义了一个全局变量x,并且在函数内部打印之前给其赋值,又 在函数外部为其赋不同的值,那么print会打印哪一个值呢?
def global_func():
global x
print(x)
x = 200
x = 100
global_func()
结果是print出100,并不是当前作用于下的200,其原因在于x = 200
定义在print之后,当没有在print语句执行 之前为x赋值的话,函数会在全局作用域下查找赋值。
可以在设置函数形参的时候为函数传递默认参数值,用来当调用时没有设置参数响应参数之时,如果调用时提供了 相关的参数值,则会覆盖默认参数值。
def printSomething(msg, times = 2):
print(msg * times)
printSomething('ha') #'haha'
printSomething('xi', 3) # 'xixixi'
需要注意的是,只有在形参列表末尾的那些参数才可以拥有默认参数。也就是说,在没有默认参数的参数前面不能 有设置了默认参数的参数。
当参数较多的时候,可以在调用的时候,通过形参标识符直接为关键参数赋值,这样可以使得函数调用更灵活,而 且不受形参顺序的影响(因为会有标识符来确认参数位置),如下例:
def key_para(a, b=1, c=2):
print('a =',a,',b =',b,',c =',c)
key_para(1) #a = 1 ,b = 1 ,c = 2
key_para(2, b=3, c=5) #a = 2 ,b = 3 ,c = 5
key_para(c=3, a=100) #a = 100 ,b = 1 ,c = 3
下午,发现了一个JavaScript30计划,也就是30天,每天用纯JS(ES6)写一个页面。今天做的是做一个键盘模拟鼓点的页 面,其中需要掌握的知识点如下:
- 按下键盘事件结合keyCode,来确定哪个键位被按下(每个键位的keyCode是唯一的)。
- 使用ES6字符串模板以及querySelctor()来确定与按下键位相关联的div块,以便于改变其样式。
const key = document.querySelector(
div[data-type="${event.keyCode}"])
.字符串模板的使用方法是,将字符串包裹在反引号``中,字符串中的变量部分用${}包裹。 - 使用Array.from()方法将类数组对象以及可迭代对象转变为真正的数组。
- 在键盘按下之后,相应的div会发生transition样式变化,故而显示变化之后需要清除这些变化,会使用到一个
transitionend
事件,表示CSS中触发了transition属性之后的响应。 Element.classList
表示元素的class类数组列表,可以通过其.add()
和remove()
方法,添加或者移除响应的类名,以达到div样式的切换。
今早重写了昨天的JS30效果,用以检测掌握程度。过程中注意到background-size: cover;
的CSS属性,并不明晰。 查询文档,发现此CSS属性有三种类型的值,第一种是例子中用到的cover,第二种是contain,第三种是width/height. 第三种好理解,前两种的区别是:cover表示背景图片尺寸会保持图像宽高比,尽可能放大,最大为原始大小。如果图 像的宽或者高等于容器的宽或者高的时候,它会停止放大,哪怕此时某一部分还是空白的。后者表示背景图片尺寸保持 图像宽高比,尽可能方法,一直到充满整个容器,如果宽或者高溢出容器,则会按照位置裁剪。
昨天的JS30任务是写一个钟表效果,在指南文档的提示下,我能够将基本的逻辑写下来,但是,期间主要出现了两 大问题:第一是,在new Date()
的时候,将其放在了更新时间函数的外面,使得每次调用函数的时候,时间并咩 有得到更新。其次是,关于三针转动角度的问题,我忽略了指针初始位置,需要在旋转开始时先旋转90度,使其到 达零点位置。
昨天的重点是 CSS3 transform
问题。需要多加应用。
JS30 第三个任务我可以通过作者的提示完成基本功能,共用了22行代码(不包括 CSS),作者通过遍历添加事件,只用了6行代码,说明目前我还是停留在写出面条式代码的阶段,但是,好现象是,我能够通过自己写出功能,这是进步。
说回任务本身。昨天的任务涉及到了 dataset 属性,CSS 全局变量的使用,这两个东西是我前面没有接触到的。
dataset 属性允许访问所在DOM元素自定义的data属性列表,一般以 "data-" 打头来命名,并且只可以包含数字字母以及 -.:_ 四个字符组成,它的结构是一个DOMString映射表,在访问的时候,其前面的 data 以及特殊符号被去除。例如,在任务中,给每个表单元素设置了 "data-sizing" 属性,取值为 "px",由此可以通过this.dataset.sizing
来访问设置的 data-sizing 属性。
CSS全局变量是CSS允许以变量的形式,在:root
伪元素下设立一些常用的重复使用的样式属性,在需要使用的位置使用 var()
的形式来访问引用。在本例中,通过使用根元素 :root
选择器来在根元素(即HTML标签)上设置了 --base, --spacing, --blur 三个全局变量,为其赋初始值,并在 img 元素上进行引用。如下:
img {
background-color: var(--base);
padding: var(--spacing);
filter: blur(var(--blur));
}
这样做的好处是,如果页面中多次引用了某个变量,例如某个字体颜色,在需要改变页面中所有的颜色时,只需要将变量的初始值一处进行修改,则会应用到全部引用的位置。在这个例子中,通过借助 style.setProperty()
来动态修改 CSS 变量,而达到表单元素变化时,CSS变量随之改变,则应用到图片上的样式也同时改变,而达到目的。类似于Sass等中的CSS变量。只不过 Sass 中以美元符号 $ 打头,而CSS全局变量则以 -- 打头。
额外需要注意的是,style.setProperty
的语法,其可以接受三个参数,分别是属性名、值以及优先级(可以通过 !important 来提高优先级)。举个例子,要设置一个 div 元素的 margin 值为 0 auto
,可以这样设置: document.querySelector('div').style.setProperty('margin', '0 auto')
; 其实相当于 JQuery 的element.css()
操作。
day4 的任务中,新见了一个控制台调试技巧:console.table
,这个输出方式会将数组或者 object 中的可枚举属性以表格的形式输出。
其次就是 Array 的一一些操作方法的熟练使用问题,尤其是 Array.reduce()
方法,其可以接受一个回调函数和一个操作初始值,回调函数接受两个参数,第一个参数代表和初始值作用后的累加值,第二个参数表示数组中的所有遍历元素(从左到右),而如何累加,则有函数部分决定,也就是说,这里的累加并不是指加法,而是一个积累的作用过程。例如下面的例子:
[1, 2, 3, 4, 5, 6].reduce((result, val) => result - val, 10)
则实现以10为基础,进行一个累减操作。也就是 10 - 1 - 2 - 3 - 4 - 5 - 6 = -11;
今天遇到一个 JS 的新操作——document.createDocumentFragment
,此特性用于创建一个空白的文档片段。也可以理解为一个空白的 DOM 元素容器,它同样可以赋值给一个变量:
let frag = document.createDocumentFragment();
这个特性的优势在于,其只是一个需要附加到 DOM 树上的 DOM 子元素容器,开始存在于内存之中,当此元素被插入到 DOM 树之后,这个结构会被其上面附加的 DOM 节点代替,故而不会引起页面回流,故而不影响页面性能。
参考这里。
看了网上面向对象式的轮播图组件,才算是对面向对象思维有了一次实践意义上的认知。所谓面向对象就是一种组件化的包装,而留一个实例化的接口。一般情况下,采用构造函数实例化的形式。在 ES6 中,提供了 class
关键字,可以用更好的形式展现面向对象思维。难怪 JJC 会说,首先你是一个程序员,然后你才是一个前端程序员。
另外,在编程过程中,函数应该尽可能小而美,这样的好处是代码条理比较清晰,而不是大杂烩一般。实现一个功能,首先是划分需要实现哪几条任务,进行功能实现上的划分,也就是在 MIT 公开课上,老师思维逻辑图的原因。
昨天去面试,遇到几个题,其实并不难,但当场没能给出很理想的答案,今天回顾一下。
- 不用
Math
和数组排序方法,取出数组中的最大值和平均值
这个题我在看书的时候遇到过,但还是表现很含糊,可见看书的时候没有自己练习,只知其然的缘故。其实就是包装一个Math.max()
方法,下面给出解决。
// 返回数组最大值
function max(arr) {
var max = arr[0];
for (var i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// 返回数组平均数
function getArg(arr) {
// 最简单方法是使用reduce()累加再求平均值,但不允许
var sum = 0,
len = arr.length;
for (var i = 0; i < len; i++) {
sum += arr[i];
}
return sum/len;
}
- 实现这样一个函数:传入一个小数,返回其保留两位小数的结果 当时给出的思路是,用
indexOf
判断小数点的位置,然后用slice()
截取位置后两位以前的部分,最后还需使用parseFloat()
转为 Number。是这样:
function keepTwoPlaceDecimal(num) {
var strNum = num.toString();
var indexOfDot = strNum.indexOf('.') + 3;
return parseFloat(strNum.slice(0, indexOfDot));
}
现在一想,真实够折腾,而且当传入的数字没有两位以上小数或者根本找不到小数点时,程序并不会实现功能。有一个 toFixed()
方法,可以通过传入参数,直接控制保留的小数位数,并且在位数不足时会自动补0.位数超过要求四舍五入截取。
function keepTwoPlaceDecimal(num) {
return parseFloat(num.toFixed(2));
}
- 使用 HTML + CSS 实现一行文本超出一定范围自动换行 这个题我完全没有思路,下来一查,竟然有
word-break
和word-wrap
这种特性,这位特性以前是见过的~在几个 id 分别为 wrap1, wrap2 的 div 上分别应用以下样式:word-break: normal | break-all | keep-all;
normal 表示使用默认的换行规则,break-all 表示对于非中日韩文本,可以在任意字符间断行。keep-all 表示 CJK 文本不换行,其他字符像 normal 时一样换行。
div { margin-top: 20px; } #wrap1 { width: 200px; border: 1px solid #000; word-break: break-all; } #wrap2 { width: 200px; border: 1px solid #000; word-break: keep-all; }
效果如下:
word-break: break-all
word-break: keep-all
关于几个相对单位:
rem
: 以设置在 root 元素的font-size
属性值为标准,也就是 1rem 等于一倍的 root 元素的 font-size;em
: 以当前字体的font-size
属性值为标准,也就是 1em 等于一倍的 font-size;ex
: 以当前字体的高度值为标准的单位值,以小写状态为依据,1ex = 1 font height. 在大多数字体下,1ex = 0.5em;vh
: 1/100 的视口高度值
今天学到的: vertical-align
属性用来指定行内元素以及表格元素的对齐方式。其大部分取值相对于父元素来讲的。针对行内元素与表格元素的标准当然是不一样的。对于行内元素来讲,当属性值为 top
的时候,表示其与整行的最顶端对齐。
CSS 指定字符编码的写法:@charset 'UTF-8'
.
在表单元素中,文本框和按钮采用不一样的盒子模型,前者是标准盒子模型,后者是 IE 盒子模型。
对于 Sass 的嵌套特性,不应该用得太浪,因为,嵌套层次过深,其编译出来的 CSS 会十分冗余,在降低代码整洁度的同时,更是大大影响页面性能。
Sass 中的 Mixins 常用的一点是处理 CSS3 属性中的前缀属性,可以使编码量大大降低。例如,可以包装下面这样一个关于 border-radius
的混合:
@mixin borderRadius($border-radius: 10px) { border-radius: $border-radius; -o-border-radius: $border-radius; -moz-border-radius: $border-radius; -webkit-border-radius: $border-radius; }
这个 Mixins 设置了一个大小为 10px 的圆角,在需要的时候,使用 @include borderRadius;
来调用,如果想改变大小,只需要更换参数即可:@include borderRadius(20px);
继承一般用于提炼出公共样式,然后在需要的地方通过 @extends
来调用。但是,如果调用的类名组织的样式在其他地方出现过的话,它会把出现过的该类下的所有代码全都继承过来,使得代码失去控制。
%placeholder
特性是十分强大的特性,通过 % 定义的样式,只要不通过 @extends
调用,它就不会产生任何多余的代码,相当于没存在过,可以说,这个特性完美滴解决了前面继承的问题。
Vue 在过去的一年飞快成长,已经是前端开发框架中的佼佼者之一。因为其简单易上手等优点,很快为广大开发者接受。但是,如果你是一名并没有实际开发经验,不了解数据绑定,组件化思想的初学者,很容易在这些基本概念中眩晕(我便是如此)。在这种时候,一定不要着急,或者说气馁,要沉下气来,从基本的原理和概念入手学习,做到不乱于心。
Vue 的优秀特性主要表现为:双向数据绑定以及组件化的构建形式,同时 Vue 提供了一些第三方的轻量库,开发者借助这些库可以实现各种开发需求。下面是一些基本概念的东西。
- 全局 API:Vue 提供一些全局的操作函数,例如
Vue.extend()
可以在 Vue 基础构造器之上,创建一个它的“子类”,其可以接受包含该组件选项的对象。而对于 Vue 的插件,例如 Vue-router ,在使用的时候,需要使用Vue.use()
方法进行注册。 - 选项:对于数据和 DOM ,Vue 都提供一些基本的选项,以便于数据渲染和 DOM 关联。对于数据选项,有最基本的
Data
属性,来表示 Vue 实例的数据对象,可以通过vm.$data
来访问原始数据对象。Vue 使用props
属性来接收来自于父组件的数据,它可以是简单的数组,也可以是进行配置高级选项(类型检测、默认值)的对象。通过computed
计算属性来进行数据操作。除此之外,还有watch
选项进行表达式观察,使用methods
选项定义示例方法。
用于 DOM 观察的选项较少,el
用于指定一个 DOM 元素作为实例的挂载目标。使用 template
字符串模板作为实例的标识,其可以替换 el
指定的挂载元素。
- 生命周期钩子选项。Vue 同样提供了一些 Vue 组件生命周期特定时期的钩子。下图是 Vue 组件的生命周期示意图:
Vue 还有一些基本 API ,可参考其文档
值得注意的是,还有一些基于实例的操作,可以通过 vm.$
的形式来进行访问。例如对于一个组件示例 app, 我们可以通过 app.$on('click', function () {})
来为其绑定点击事件。可以通过 app.$data
来访问 app 的 data 方法下的所有数据。
- 指令。Vue 提供一些基本的操作指令,例如
v-text
可以更新元素的文本内容,v-if
可以进行基本的条件判断渲染,v-bind
用于绑定 DOM 元素的属性,v-model
在表单控件上实现数据双向绑定。
Tips: v-text
和 t-html
的区别:前者相当于插入 textContent
的内容,而后者则相当于 innerHTML
的内容,后者安全性不高。在下面的实例中,可以很清晰地看到区别:
<template>
<div id="app">
<h1 v-text="imgEle"></h1>
<h2 v-html="imgEle"></h2>
<!-- <router-view></router-view> -->
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
imgEle: '<img src=\'http://i2.muimg.com/567571/6c2cfa8bcf63a117.jpg\'>'
}
}
}
</script>
h1
显示的内容为 imgEle 指示的字符串内容,而后者则会渲染出一张图片来。