计划按如下顺序完成这篇笔记:
- 理念。
- 属性复制和继承。
- this/call/apply。
- 闭包/getter/setter。
- prototype。
- 面向对象模拟。
- jQuery基本机制。
- jQuery选择器。
- jQuery工具方法。
- jQuery-在“类”层面扩展。
- jQuery-在“对象”层面扩展。
- jQuery-扩展选择器。
- jQuery UI。
- 扩展jQuery UI。
这是笔记的第7篇,聊聊jQuery基本机制,学习的同时,我们试图实现一个缩略版本的jQuery,我们叫他jQ。
我们认为读者在阅读本篇之前,对jQuery的使用是熟悉的。
第7篇到第9篇是一个单元,在这个单元中,我们将深入jQuery内部,充分学习JavaScript的最佳设计、编程实践。
作者博客:http://blog.csdn.net/stationxp
作者微博:http://weibo.com/liuhailong2008
转载请取得作者同意
首先,预热一下语法。
1、预热语法
看下面代码:
//代码段1
(function(){
console.log('this is a function be called immediately.')
})();
第一对小括号中是一条语句,返回一个函数,然后通过第二对小括号对这个函数直接进行调用。运行输出:this is a function be called immediately.可以传参数给这个参数,在JavaScript中,$和_都是合法的变量名。//代码段2
(function(_){
console.log(_); //输出:window,视浏览器输出的具体内容不同
})(this);
在全局上下文中this指向window。可以通过如下方法获得返回值。//代码段3
var f = (function(_){
function func(){
console.log('i am invoked by ' + this , 'arguments:' + _ );// output : i am invoked by [object Window] arguments:param value
}
return func;
})('param value');
f();
也可以将需要返回的数值或方法直接附加为window的属性,达到“返回”的目的。//代码段4
(function(){
function func($$){
console.log('i am invoked by ' + this );
}
window.func = func; // 相当于直接定义了全局函数func
window.$$ = new func(); //相当于定义了全局变量 $$ ,在JavaScript中,$$ 是合法的变量名。
})();
func();
console.log($$.toString());// output : [object Object]
2、预期功能
我们将实现一个js代码框架,jQ,预期实现如下功能:
2.1、通过jQ('#id')可以通过id取到dom对象。
2.2、对jQ对象(即通过jQ方法返回的对象),可以使用html()方法获取其内容或者设置其内容,语法如下:
jQ('#id').html();//返回其内容
jQ('#id').html('new content');//设置其内容
2.3、可以用$$代替jQ,语法如下:
$$('#id').html();
3、实现
3.1、基于前面的语法基础,我们视图实现2.1提出的功能。
代码段5
<!DOCTYPE html>
<html>
<head>
<title>jQ</title>
<meta charset="utf-8">
<script type="text/javascript" language="javascript">
(function(){
var jQ = function(id){
if(!id){
return {}; // return empty object
}
if(id[0]=='#'){
id = id.substr(1);//remove the first letter '#'
}
var domEle = document.getElementById(id);
if(!domEle){
return {};
}
return domEle;
}
window.jQ = jQ;
})();
console.log(jQ('#divTest'));
</script>
</head>
<body>
<div id="divTest">blabla</div>
</body>
</html>
获取到dom对象后直接返回了。这种做法不足取,需要封装一下,最好以function object(function是js中的一等公民,功能最强)的形式返回。而且希望返回值是jQ“类”的实例。//代码段6
(function(){
var jQ = function(id){
var ret = new jQ();
ret.innerDom = 'blabla';
return ret;
}
jQ.prototype = {
innerDom : null
}
window.jQ = jQ;
})();
console.log(jQ('#divTest'));
Uncaught RangeError: Maximum call stack size exceeded ,死循环了。直接new不可用用的话,那可以用工厂方法。//代码段7
(function(){
var jQ = function(id){
var ret = jQ.prototype.getInstance(id);
return ret;
}
jQ.prototype = {
innerDom : null,
getInstance :function(id){
//todo : init innerDom by id
return this; // 调用者,即jQ
}
}
window.jQ = jQ;
})();
console.log(jQ('#divTest')===jQ('#divTest1')); // output : true
上面的最后一行代码,意图构建两个不同的对象,结果返回的对象相同,这是错误的。改正后的代码如下所示。//代码段8
(function(){
var jQ = function(id){
var ret = new jQ.prototype.getInstance(id); // 增加new关键字
return ret;
}
jQ.prototype = {
innerDom : null,
getInstance :function(id){
//todo : init innerDom by id
return this; // 调用者,即jQ
}
}
window.jQ = jQ;
})();
console.log(jQ('#divTest')===jQ('#divTest1')); // output : false
根据new关键字的语义:var ret = new jQ.prototype.getInstance(id);等同于var ret ={};jQ.prototype.getInstance.apply(ret);//即通过ret调用getInstance方法,getInstance方法中的this绑定为retret.__proto__ = jQ.prototype.getInstance.prototype;//指定ret的原型为getInstance的原型,这里会出问题,因为getInstance的原型是Object(几乎是空)。为了弥补new关键字的缺憾,修正代码如下://代码段9
(function(){
var jQ = function(id){
var ret = new jQ.prototype.getInstance(id);
return ret;
}
jQ.prototype = {
innerDom : null,
getInstance :function(id){
//todo : umimpl init innerDom by id
this.innerDom = 'dom by '+id;
return this; //this调用者,即新创建的对象
},
html:function(){
//todo : impl the method
return this.innerDom;//this调用者,即新创建的对象
}
}
jQ.prototype.getInstance.prototype = jQ.prototype;//新增加代码,由于是传引用,不用担心循环引用的问题
window.jQ = jQ;
})();
console.log(jQ('#divTest').html()); //output : dom by #divTest
console.log(jQ('#divTest2').html()); //output : dom by #divTest2
3.2、现在增加2.2描述的功能:html方法
//代码段10
<!DOCTYPE html>
<html>
<head>
<title>jQ</title>
<meta charset="utf-8">
</head>
<body>
<div id="divTest">blabla</div>
<script type="text/javascript" language="javascript">
(function(){
var jQ = function(id){
var ret = new jQ.prototype.getInstance(id);
return ret;
}
jQ.prototype = {
innerDom : null,
getInstance :function(id){
if(id && id[0]=='#'){
id = id.substr(1);//remove the first letter '#'
}
if(id){
var elm = window.document.getElementById(id);
this.innerDom = elm;
}
return this;
},
html:function(newhtml){
if(arguments && arguments.length>0){
if (this.innerDom && this.innerDom.innerHTML){
this.innerDom.innerHTML = newhtml;
}
}else{
return this.innerDom && this.innerDom.innerHTML;
}
}
}
jQ.prototype.getInstance.prototype = jQ.prototype;
window.jQ = jQ;
})();
console.log(jQ('#divTest',window).html()); //output : blabla
jQ('#divTest',window).html('BRAND NEW'); //页面内容随之改变
console.log(jQ('#divTest',window).html()); //output : BRAND NEW
</script>
</body>
</html>
3.3、通过$$引用
2.3描述的功能更简单,只需在window.jQ = jQ;后面加一句:
window.$$ = jQ;
调用的语句修改为:
console.log($$('#divTest',window).html()); //output : blabla
$$('#divTest',window).html('BRAND NEW'); //页面内容随之改变
console.log($$('#divTest',window).html()); //output : BRAND NEW
功德圆满!
分享到:
相关推荐
CSS完全参考手册3.0 ApacheMenu_zh_CN DIV+CSS(WEB标准) hibernate学习笔记 java web 标签大全 JavaScript 中文版 JDK_API_1_6_zh_CN jquery 1.7 中文 api 修正版 Jsp_sevlet中文API jsdom Oracle九阴真经 Servlet ...
2020年Java基础教程(全资料+笔记+源码): 2020年javaweb全套教程: Mysql: Oracle: JDBC: C3P0: 前端技术 HTML、CSS、Javascript: jQuery-: Ajax: Vue: 微信小程序: 动态网页: 编程强化 JVM优化: 数据...
58同城源码java JavaScript:理解奇怪的部分 这些是我关于深入学习 JavaScript 的精彩课程的笔记。 如果您想了解 JavaScript 引擎是如何在幕后工作的,我强烈建议您查看本课程,您可以在 中找到该课程。 生成的目录 ...
程序员专用刷题 布局 永久链接 默认 / 高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有...
Vue 系列 学习笔记阅读目录Vue 双向绑定原理,浅析 MVVMVue 源码概要VueX 状态管理常用地址链接Vue 是一个开源框架,最新版本已经更新到了 3.0,当前系列基于 2.X(单独发文 3.0),是一个独立的 Javascript 框架,...
程序员专用刷题高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有人也可以随意提问。 浏览...
程序员专用刷题 布局 永久链接 默认 / 高级 JavaScript 教学大纲 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有...
程序员专用刷题 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以即使周围没有人也可以随意提问。 浏览并创建 办公时间(见) 获得一对一帮助,或安排见面时间 课程说明 在这门...
程序员专用刷题 布局 永久链接 默认 / Silabus Grafika Komputer (kelas A) 如果您是教师或对课程设计感兴趣,请参阅文档。 课程: 导师:艾丹费尔德曼, 需要帮忙? 它将消息摘要发送给不在房间里活动的人,所以...