0%

JS 语法前提

面向对象实现无非三个特征,封装,继承,多态。

JS 实现基于构造函数(constructor)和原型链(prototype)。

JavaScript 引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。

关于 this 知识:

  • 创建一个空对象,作为将要返回的对象实例。
  • 将这个空对象的原型,指向构造函数的 prototype 属性。
  • 将这个空对象赋值给函数内部的 this 关键字。
  • 开始执行构造函数内部的代码。
  • if Constructor returns object, instanceObject will get the object, or else get ‘this object’.

JS 实现

构造函数实现封装:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name, age) {
// 优先级最高
this.name = name
this.age = age
}
// prototype 实例共享的属性和方法,节省内存
Person.prototype.type = 'human'

Person.prototype.sayName = function() {
console.log(this.name)
}

var instanceObject = new Person('张三', 22)

实现继承:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 构造继承
function Student (name, age, gender) {
// 借用构造函数继承属性成员
Person.call(this, name, age)
// 可以覆盖,重写
this.gender = gender
}
// 复制父构造函数的原型对象
// 也可以使用Student.prototype = new Person(),但会有Person的实例属性
Student.prototype = Object.create(Person.prototype)
// 单个方法的继承
|| Student.prototype.print = function() { Person.prototype.print.call(this) }
// 指定原型对象的构造函数
Student.prototype.constructor = Student
// 可以覆盖,重写
Student.prototype.method = '...'

var instanceObject = new Student('张三', 22, 'man')
// 此时,instanceObject instanceof Student || Person 都为true

实现多重继承 Mixin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function M1() {
this.hello = 'hello'
}
function M2() {
this.world = 'world'
}
function S() {
M1.call(this)
M2.call(this)
}
// 继承 M1
S.prototype = Object.create(M1.prototype)
// 继承链上加入 M2, 对象覆盖
Object.assign(S.prototype, M2.prototype)
// 指定构造函数
S.prototype.constructor = S

var s = new S()
s.hello // 'hello:'
s.world // 'world'

ES6 实现

可以看作是 Syntactic sugar

类的声明:

1
2
3
4
5
6
7
8
9
10
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
sayName() {
console.log(this.name)
return this.age
}
}

继承的实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Student extends Person {
constructor(name, age, gender) {
// super函数必不可少,调用父类的constructor(x, y)
// 在es6内部实现中,子类的this必须通过父类的构造函数完成塑造
super(name, age)
// 由super返回了Student的实例,相当于Person.prototype.constructor.call(this)
this.gender = gender
}
toString() {
return this.gender + ' ' + super.sayName() // 调用父类的toString()
}
}

var instanceObject = new Student('张三', 22, 'man')
// instanceObject的__proto__指向Student的prototype, 有toString方法,
// 它的__proto__指向Person的prototype, 有sayName方法

HTML5 拖曳上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
$(function(){ 
//阻止浏览器默认行
$(document).on({
dragleave: function(e){ //拖离
e.preventDefault()
},
drop: function(e){ //拖后放
e.preventDefault()
},
dragenter: function(e){ //拖进
e.preventDefault()
},
dragover: function(e){ //拖来拖去
e.preventDefault()
}
})

var box = document.getElementById('drop_area') //拖拽区域
box.addEventListener("drop",function(e){
e.preventDefault() //取消默认浏览器拖拽效果
var fileList = e.dataTransfer.files //获取文件对象
if(fileList.length == 0){ //检测是否是拖拽文件到页面的操作
return false
}
//检测文件是不是图片
if(fileList[0].type.indexOf('image') === -1){
alert("您拖的不是图片!")
return false
}

//拖拉图片到浏览器,可以实现预览功能
var img = window.URL.createObjectURL(fileList[0])
var filename = fileList[0].name //图片名称
var filesize = Math.floor((fileList[0].size) / 1024)
if(filesize > 5000){
alert("上传大小不能超过5M")
return false
}
var str = "<img src='" + img + " width='60xp' height='60px''><p>图片名称:"
+ filename+"</p><p>大小:" + filesize + "KB</p>"

$("#preview").html(str)

//上传
xhr = new XMLHttpRequest
xhr.open("post", "upload.php", true)
xhr.onreadystatechange = function(){
if (xhr.readyState !== 4) return
// 说明响应数据下载完成
console.log(xhr.responseText)
}
xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest")
var fd = new FormData
fd.append('pic', fileList[0])
xhr.send(fd)
}, false)
})

jQuery 结构

jQuery version 1.3 2.2

jQuery的设计哲学:write less, do more. 在browser端,引入即可使用。

  • 一切皆对象,jQuery也是对象
  • jQuery 是一个不需要new的普通函数
  • jQuery 返回jQuery对象

    最基本构造函数方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var $ = jQuery = function() {
    // todo
    }
    // 别名
    jQuery.fn = jQuery.prototype = {
    // 扩展原型对象
    method: todofunction,
    }
    //使用
    var $instance = new $()
    $instance.method()
    这是一般生成对象方式,需要实例化,使用时需声明变量,用起来麻烦。

去掉外部new

第一个想法要去掉外部的new,直接return jQuery(),必然会出现无限循环。
因此,可以return jQuery.init()
但是,同时考虑返回的jQuery对象需要有jQuery.prototype里的属性方法。
return jQuery.prototype.init()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var $ = jQuery = function() {
// new 返回实例化jQuery对象
return jQuery.prototype.init()
}
// 别名,对象方法属性
jQuery.fn = jQuery.prototype = {
// 扩展原型对象
init: function(){
return this
},
method: todofunction,
}
//使用
var $instance = $()
$instance.method()

上述方式,init里this属性将覆盖掉外部属性,返回的jQuery对象将公用一条作用链,破坏作用域的独立性。
需要将jQuery.prototype.init()作用域独立出来,即return new jQuery.prototype.init()

重新建立连接,跨域访问

决定用return new jQuery.prototype.init(),便要考虑如何访问jQuery.prototype的属性。
方法便是覆盖,重新建立连接。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var $ = jQuery = function() {
// new 返回实例化jQuery对象
return new jQuery.prototype.init()
}
// 别名, 对象方法属性
jQuery.fn = jQuery.prototype = {
// 扩展原型对象
init: function(){
return this
},
method: todofunction,
}
// 覆盖,重新建立连接
jQuery.prototype.init.prototype = jQuery.fn
//使用
var $instance = $()
$instance.method()

如此一来,new出来的jQuery对象,prototype 便指向 $.prototype。
jQuery对象便继承了jQuery.fn的方法。

避免全局污染

直接写成代码块的形式显然不合适。
这里采用了立即调用函数的方式进行封装,同时将window当做参数传入,减少变量链的长度。
传入形参undefined,是因为在早期ECMA标准中,undefined不是关键字,可是重写。为了避免这个因素,undefined当做形参,不传入实参,undefined 就等于真的undefined。防止了重写。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(function(window, undefined) {
// 对外暴露的工厂函数
function jQuery() {
return new jQuery.fn.init();
}
// 给原型提供一个简写方式
jQuery.fn = jQuery.prototype = {
constrcutor: jQuery
};
// init是jQuery中真正的构造函数 ==> 入口函数
var init = jQuery.fn.init = function() {
};
// 替换构造函数的原型 为 jQuery工厂的原型
// 为了实现插件机制,让外界可以透过jQuery.fn扩充方法。
init.prototype = jQuery.fn;
// 把工厂通过两个变量暴露出去
w.jQuery = w.$ = jQuery;
}(window));

为了兼容Node.js,可以在这个外面包一层(function( global, factory ),用于判断所处环境。

感慨

人是一种多么容易满足的生物。

啤酒,性,暴食,致幻剂,随意就抚平了。愚昧如待宰,浅薄不知道。离岸的船里仅仅一人我。

悲哀啊,约拿的信心几人能有。

animation

动画,一帧一帧地播放静态页面。
在前端领域无非两种方式实现:

  • JavaScript用DOM API的setInterval函数实现
  • 用CSS3的transition、animation属性实现

setInterval方式

1
2
3
4
5
6
7
8
9
function animate(element) {
//调用此函数先清除timeId,防止重复调用错误
clearInterval(element.timeId);
element.timeId = setInterval(function () {
todoing()
//完成todoing应清除timeId clearInterval(element.timeId);
}
}, 10);
}

CSS transition animation

1
2
3
4
transition: property duration curve  delay;
<!-- 事件、伪类触发,element property的变化,transition自动脑补 -->
transform: translate(x, y) || scale(x, y) || rotate(180deg) || skew(180deg, deg);
<!-- 同时transform也可以操控3dx左负右正;y上负下正;z里负外正 -->
1
2
3
4
5
6
7
animation: name duration curve delay count direction;
@keyframes name {
/* percent represent during time*/
0%{}
50%{}
100%{}
}

流氓无产阶级的孤独

“在看守所里的感觉比家里感觉好多了,在家里一个人好无聊”

我的评价

人本质的孤独,漫不经心地反应在每一个卑琐小人身上。

资本世界的异化反抗

初民气概,“帝力于我何有哉。”

隔绝

隔绝是注定的,福报恶报皆是心生。

笑容

笑容带着恐惧权衡,细看是阴险乖戾,更深处是对不知是谁的顺服。
其表现是不自觉地歇斯底里。
理性的暴躁,来自情绪的不安,生理的燥欲。

统帅

中原王朝的庸常君主,似吾。

年级

因为年轻而无处挥洒的身体,仲夏季节的阳光。害怕阴阳二气攻守之势异也。
有精力,却无激情。散漫,无浪漫。经验是恒久的,不会再欺骗自己。
与心里深渊对视,毋庸置疑,不可言说,也不知向何人说。

至此

新木发散暮气

清醒的理智

快乐的基础是理智,同时作为正反馈,形成清醒开放的稳定系统。
我是能清晰地感受到,愉悦时更加理智清醒。

学而时习之,不亦说乎?有朋自远方来,不亦乐乎?人不知而不愠,不亦君子乎?

我快乐吗?

我生活的常态是快乐还是忧愁?

如果快乐是故意的,是需要花费精力时间去寻找去实现,那么人的本质就绝对不是快乐的,或者说快乐不是人的底色。

我的快乐属于那种呢?经验世界里的快乐,是不是真实不虚的?

夫子说:“七十而从心所欲,不逾矩。”

前路漫漫

浴乎沂,风乎舞雩,咏而归。

言语是护城河

我本是沉默的人,言语是我的护城河。

人都说花言巧语、甜言蜜语 ,我却不能投人所好。说的多便惹人厌烦,即便说的妙,人的称赞也是转瞬即逝。需知人心之险,甚于山川。

理解有多难,言语就有多伪善。

沉默的好处是省力

周作人说,沉默的好处是省力、省事。自己想说服别人,或是有所辩解,照例是没有什么影响,而且愈说愈渺茫,不如及早沉默,虽然不能因此而说服或辩明,但至少是不会增添误会。

周作人还说,人的脸上固然不可没有表情,但我想只要淡淡地表示就好,譬如微微一笑,或者在眼光中露出一种感情——自然,恋爱与死等可以算是例外,无妨有较强烈的表示,但也似乎不必那样掀起鼻子,露出牙齿,仿佛是要咬人的样子。这种嘴脸只好放到影戏里去,反正与我没有关系,因为二十年来我不曾看电影。

真是妙极。不增添麻烦,亦无忧无惧,正是老派人信条。如我外公、母亲。

口才与道理

国内公认的口才好,便是辩论、争吵的伶牙俐齿。上天生我喉咙、舌头当然不是用来和人争斗。

语言是思维的载体,言语如刀枪,未出口已经先伤己了。

发心不正的言语是索取, “人心比万物都诡诈, 坏到极处”,言语就变成了一种肉体本能,如条件反射般地。这难道不是在伤害人、作践人吗?

何时可

那修行未到的话,就先沉默吧。