上周邀朋友之请,写了JQ系列,但感觉对于初学者来说,有点复杂,或者摸不着头脑,所以,这次要从0起步了,从最基础的开始写起,下面我整理了一下目录,呵呵!
Javascript基础与面向对象基础~目录
第一讲 啥叫编程,啥叫程序员
第二讲 Javascript中的变量及变量的类型
第三讲 Javascript中的语句如何被执行,如何改变执行顺序
第四讲 Javascript中的类对象
第五讲 Javascript中的方法,类中的方法
第六讲 Javascript中的事件机制
第七讲 Javascript中的闭包
第八讲 从人类的起源谈面向对象
感谢您的阅读!
本文链接
大家会如何设计一个缓存呢?
一个简单的Cache
var __cache = {},
Cache = {
get: function(__name){
return __cache[__name] || undefined;
},
set: function(__name, __value){
return (__cache[__name] = __value)
}
};
this.Cache = Cache;
})();
alert(Cache.get("name")); //undefined
Cache.set("name", "Bob");
alert(Cache.get("name")); //Bob
但这不是jQuery想要的
jQuery要解决的是对应元素的缓存数据。
例如,我们用document.getElementById获得了一个元素element,然后有一个对应的参数value的属性名是key,那么我们想保存到缓存里,那么我们需要告诉缓存element、key、value才能保存数据,而想要获得这个值,则要告诉缓存element和key,才能得到value。
所以jQuery的缓存实际上是直接绑定到对象中的。
为什么?因为这样简单啊。
用上面的方法,先要将element转成字符串或者数字对应缓存里的对象,然后再用该对象来缓存不同key的value……这……太……麻……烦……了!!
实际上,由于Javascript没有Hash值方法,所以对象转字符串或数字并没有太好的方法,当然绑一个ID在元素上除外。
做一个别人一般不会用的令牌
但是绑定在对象上有一个问题,如果属性名用什么呢?
如果这个属性名别人也拿去用就悲剧了,比如我用.cache绑定数据,但是另一个库也有.cache来绑定数据,就……
所以,jQuery做了一个正常情况下别人不会用的令牌。
replace函数将core_verision中的非数字全部替换掉,所以最后这个令牌是一个jQuery后面加一个随机数,比如:
jQuery20018518865841457738
jQuery.hasData
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
return !!elem && !isEmptyDataObject( elem );
};
从这个函数可以看出,如果elem是DOM Element对象,则数据存在jQuery.cahe中,否则存在存在elem对象中。
jQuery.data & jQuery.removeData
return internalData( elem, name, data, false );
};
return internalRemoveData( elem, name, false );
};
他们分别调用了internalData和internalRemoveData。
注意专用接口jQuery._data和jQuery._removeData传的最后一个值有些不同。
这个后面会说到。
return internalData( elem, name, data, true );
};
return internalRemoveData( elem, name, true );
};
internalData
// 判断该对象能不能绑定数据
if ( !jQuery.acceptData( elem ) ) {
return;
}
var thisCache, ret,
internalKey = jQuery.expando,
getByName = typeof name === "string",
// 由于IE6-7的DOM节点引用的垃圾回收问题,需要分开处理DOM节点和JS对象
// 真心想吐槽,这不是jQuery 2.0么!!!不是说不支持IE6-8么!!!
isNode = elem.nodeType,
// 如果是DOM节点,则使用jQuery.cache存储数据,否则使用elem本身
cache = isNode ? jQuery.cache : elem,
// 得到对象的ID号,如果是DOM节点则是其以令牌为属性名的属性值,否则是令牌
id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
// 避免为了从一个根本没有数据的对象获取数据而浪费时间
if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
return;
}
// 如果没有ID
if ( !id ) {
// 如果是DOM节点,就给他一个ID
if ( isNode ) {
elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
// 否则以令牌作为其ID
} else {
id = internalKey;
}
}
// 如果对应ID的缓存不存在
if ( !cache[ id ] ) {
// 初始化缓存
cache[ id ] = {};
// 避免对JS对象使用JSON.stringify时暴露jQuery的元数据对象,所以给对象添加toJSON方法
if ( !
译序
Three.js是一个伟大的开源WebGL库,WebGL允许JavaScript操作GPU,在浏览器端实现真正意义的3D。但是目前这项技术还处在发展阶段,资料极为匮乏,爱好者学习基本要通过Demo源码和Three.js本身的源码来学习。
国外网站 aerotwist.com 有六篇较为简单的入门教程,我尝试着将其翻译过来,与大家分享。
0.简介
这是WebGL着色器教程的后半部分,如果你没看过前一篇,阅读这一篇教程可能会使你感到困惑,建议你翻阅前面的教程。
上一篇结束的时候,我们在屏幕中央画了一个好看的粉红色的球体。现在我要开始创建一些更加有意思的东西了。
在这一篇教程中,我们会先花点时间来加入一个动画循环,然后是顶点attributes变量和一个uniform变量。我们还要加一些varying变量,这样顶点着色器就可以向片元着色器传递信息了。最终的结果是哪个粉红色的球体会从顶部开始向两侧“点燃”,然后作有规律的运动。这有一点迷幻,但是会帮助你对着色器中的三种变量有更好的了解:他们互相联系,实现了整个集合体。当然我们会在Three.js的框架中做这些。
1.模拟光照
让我们更新颜色吧,这样球体看起来就不会是个扁平晦暗的圆了。如果我们想看看Three.js是怎样处理光照的,我敢肯定你会发现这比我们需要的要复杂得多,所以我们先模拟光照吧。你应该浏览一下Three.js中那些奇妙的着色器,还有一些来自最近的一个 Chris Milk 和 Google, Rome 的WebGL项目。
回到着色器,我们要更新顶点着色器来向片元着色器传递顶点的法向量。利用一个varying变量:
varying vec3 vNormal;
void main() {
// 将vNormal设置为normal,后者是Three.js创建并传递给着色器的attribute变量
vNormal = normal;
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(position, 1.0);
}
在片元着色器中,我们将会创建一个相同变量名的变量,然后将法线向量和另一个表示来自右上方光线的向量点乘,并将结果作用于颜色。最后结果的效果有点像平行光。
varying vec3 vNormal;
void main() {
// 定义光线向量
vec3 light = vec3(0.5,0.2,1.0);
// 确保其归一化
light = normalize(light);
// 计算光线向量和法线向量的点积,如果点积小于0(即光线无法照到),就设为0
float dProd = max(0.0, dot(vNormal, light));
// 填充片元颜色
gl_FragColor = vec4(dProd, // R
dProd, // G
dProd, // B
1.0); // A
}
看看效果
使用点积的原因是:两个向量的点积表明他们有多么“相似”。如果两个向量都是归一化的,而且他们的方向一模一样,点积的值就是1;如果两个向量的方向恰巧完全相反,点积的值就是-1。我们所做的就是把点积的值拿来作用到光纤上,所以如果这个点在球体的右上方,点积的值就是1,也就是完全照亮了;而在另一边的点,获得的点积值接近0,甚至到了-1。我们将获得的任何负值都设置为0。当你将数据传入之后,你就会看到最基本的光照效果了。
下面是什么?我们会将顶点的坐标掺和进来。
2.Attribut变量
接下来我要通过Attribute变量为每一个顶点传递一个随机数,这个随机数被用来将顶点沿着法线向量推出去一段距离。新的结果有点像一个怪异的不规则物体,每次刷新页面物体都会随机变化。现在,他还不会动(后面我会让他动起来),但是几次刷新就可以很好地观察到,他的形状是随机的。
让我们开始为顶点着色器加入attribute变量吧:
varying vec3 vNormal;
void main() {
vNormal = normal;
// 将随机数displacement转化为三维向量,这样就可以和法线相乘了
vec3 newPosition = position +
normal * vec3(displacement);
gl_Position = projectionMatrix *
modelViewMatrix *
vec4(newPosition, 1.0);
}
看看效果
你看到什么都没变,因为attribute变量displacement还没有被设定你,所以着色器就使用了0作为默认值。这时displacement还没起作用,但我们马上就要在着色器材质中加上attribute变量了,然后Three.js就会自动地把它们绑在一起运行了。
同时也要注意这样一个事实,我将更新后的位置指定给了一个新的三维向量变量,因为原来的位置变量position,就像所有的attribute变量一样,都是只读的。
3.更新着色器材质
现在我们来更新着色器材质,传入一些东西给attribute对象displacement。记住,attribute对象是和顶点一一对应的,所以我们对球体的每一个顶点都有一个值,就像这样:
displacement: {
type: 'f', // 浮点数
value: [] // 空数组
}
};
var vShader = $('#vertexshader');
var fShader = $('#fragmentshader');
// 创建一个包含attribute属性的着色器材质
var shaderMaterial =
new THREE.MeshShaderMaterial({
attributes: attributes,
vertexShader: vShader.text(),
fragmentShader: fShader.text()
});
//