/*

基本类型
Undefined, Null, Boolean, Number, String.
复杂类型
Object 它是所有对象的基础类型。 引用类型
Object
创建:new Ojbect() 和 对象字面量语法{...}
读取:. 和 [...]
Array
创建:new Array()、Array() 和 数组字面量语法[...]
读取:[下标]
length:不只是只读,改变length的值,会改变数组的长度。
isArray() 判断某个对象是不是数组:https://www.cnblogs.com/fogwind/p/5884684.html
toLocalString() 调用子项的toLocalString()
toString() 调用子项的toString()
valueOf() 返回数组
join() 参数指定间隔符,默认为逗号(,)
push() 任意数量参数, 在数组末端增加项,返回新的长度
pop() 返回数组末端的值,数组长度减1
shift() 返回数组前端的值,数组长度减1
unshift() 任意数量参数,在数组前端增加项,返回新的长度
push + shift 模拟队列; unshift + pop 模拟反向队列
reverse()
sort() 先调用数组项的toString()方法转换,再比较得到的字符串。可以传入比较函数来指定排序方式
slice(start, end) 返回[start, end)的数组项,通过指定负数,则从后计算。
splice(start, deleteNum, (add0, add1...)) 返回删除项组成的数组或空数组
indexOf(item(,startIndex)) 从前往后查找,返回第一个匹配项的下标或-1
lastIndexOf(item(,startIndex)) 从后往前查找,返回第一个匹配项的下标或-1
every(function(item, index, array) (, scope)) Boolean
filter(function(item, index, array) (, scope)) Array
forEach(function(item, index, array) (, scope)) void
map(function(item, index, array) (, scope)) Array
some(function(item, index, array) (, scope)) Boolean
reduce(function(pre, cur, index, array) (, initValue))
reduceRight(function(pre, cur, index, array) (, initValue)) Date RegExp
创建:new RegExp(pattern, flags) 和 正则字面量 /pattern/flags 其中flags取值为g/i/m组合体
属性:global, ignoreCase, lastIndex, multiline, source
exec() 即使在模式中指定了g,每次执行也只返回一个匹配项,可通过多次调用exec(),得到所有匹配项。没有匹配项,返回null.
test()
RegExp构造函数属性 Function
函数(是对象)
函数名 函数声明 function name(...) {...}
其实函数名仅仅是一个包含指针的变量而已,把它赋值给其他变量时,它们指向的是同一个函数对象。
被初始化为函数的变量 函数表达式 variable = function(...) {...}
将函数名想象为指针,更容易明白为什么没有函数重载了。
函数声明提升(function declaration hoisting)
函数内部属性:arguments, this
函数属性和方法:length, propotype, call(), apply(), bind(), 基本包装类型
每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象。
使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前都一直保持在内存中,而自动创建的基本包装类型的对象,
则只存在于一行代码的执行瞬间,然后立即被销毁。举例:
var s1 = "some text";
var s2 = s1.substring(2);
其中第2行代码相当与:
var s1 = new String("some text");
var s2 = s1.substring(2);
var s1 = null;
即第2行代码中s1.substring(2)存在一个自动转换,而自动转换的基本包装类型的对象在代码执行完之后立即被销毁了。
证明:
var s1 = "some text";
s1.color = "red";
alert(s1.color); //undefined
以上代码中,color属性只是添加到了当前行自动创建的基本包装类型的对象上,赋值表达式执行完之后,对象被销毁。
在使用s1.color进行访问是,这时会产生一个新的基本包装类型的对象,当然也就没有color属性了。 Boolean Number
toFixed(), toExponential(), toPrecision(), String
charAt(index), charCodeAt(index),
concat(str1, str2...),
slice(start, end) 负数 + 长度; [start, end)
substr(start, len) 负数1 + 长度; 负数2 --> 0;
substring(index1, index2) 负数 --> 0; [min(index1, index2), max(index1, index2))
indexOf(str (, startIndex)), lastIndexOf(str (, startIndex))
trim(str)
toLowerCase(), toLocaleLowerCase(), toUpperCase(), toLocaleUpperCase()
match(pattern)
如果pattern指定了g,则返回所有匹配项组成的数组或者null;
如果没有指定g,则返回匹配项和捕获组,等同pattern.exec(str)的结果.
search()
replace()
split()
localeCompare()
String.fromCharCode(cc1, cc2...) 单体内置对象
Global
encodeURI(), encodeURIComponent(), decodeURI(), decodeURICompnent()
eval()
isNaN(), isFinite(), parseInt(), parseFloat()
undefined, NaN, Infinity, Object, Array...
Web浏览器中这个全局对象作为window对象的一部分加以实现。 Math
min(num1, num2, num3...), max(num1, num2, num3...)
//获取数组的最小值
var values = [1, 2, 3, 4];
var max = Math.min.apply(Math, values);
ceil(), floor(), round()
random()
随机取一个范围内的值
值 = Math.floor(Math.random() * 可能值的总数 + 第一个可能值)
function selectFrom(lowerValue, upperValue) {
var choices = upperValue - lowerValue + 1;
return Math.floor(Math.random() * choices + lowerValue);
} 对象
数据属性
设置
Object.defineProperty(object, property, {attribute: value(,...)})
Object.defineProperties(object, {property: {attribute: value}(,...)})
读取
var descriptor = Object.getOwnPropertyDescriptor(object, property);
alert(descriptro.attribute);
其中attribute/enumerable/writable/value 访问器属性
设置
Object.defineProperty(object, property, {attribute: value(,...)})
Object.defineProperties(object, {property: {attribute: value}(,...)})
读取
var descriptor = Object.getOwnPropertyDescriptor(object, property);
alert(descriptro.attribute);
其中attribute可取:configurable/enumerable/get/set 创建
工厂模式
function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
无法识别对象的类型,仅仅是object。
构造函数模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
每个实例都拥有自己的方法对象(Function的实例),其实这些方法做的是同样的事,完全可以共享一个方法对象,构造函数无法
实现此目的。
原型模式
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true 函数(Person) 每一个函数在创建时,都会有一个prototype属性,prototype指向函数的原型对象。
函数的原型对象(Person Prototype) 默认情况下,所有原型对象都会自动获得一个constructor属性,constructor指向函数。
函数的实例(person1, person2) 每个对象都有一个属性__proto__([[Prototype]])指向函数的原型对象。 isPrototypeOf()
alert(Person.prototype.isPrototypeOf(person1)); //true
getPrototypeOf()
alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas" 代码读取某个对象的属性时,先在当前实例查找,找到直接返回,如果没找到,则沿着__proto__查找。也就是说,
对象可以共享原型链上的属性和方法。
但是,如果直接通过对象给对象本身不存在但是在原型链中存在的属性赋值时,并不会修改原型链中属性的值,而是会在对象
中增加一个相应的属性。比如:
person1.name = "Greg";
alert(person1.name); //"Greg"—— 来自实例 屏蔽了原型中的name属性
alert(person2.name); //"Nicholas"—— 来自原型
通过delete 删除属性后又可以访问到原型中的属性了
delete person1.name;
alert(person1.name); //"Nicholas"—— 来自原型 hasOwnProperty() 判断实例本身是否存在某属性
alert(person1.hasOwnProperty("name")); //false in操作符 判断对象是否能否访问某一属性
alert("name" in person1); //true
//判断对象是否能访问原型中的某一属性
function hasPrototypeProperty(object, name){
return !object.hasOwnProperty(name) && (name in object);
}
person1.name = "Greg";
alert(hasPrototypeProperty(person, "name")); //false for-in操作
返回的是所有能够通过对象访问的、可枚举的(enumerated)属性,包括对象本身和原型链上的属性,相同属性只会出现一次。
Object.keys(object)
返回对象本身可枚举的属性。
Object.getOwnPropertyNames(object)
返回对象本身所有的属性,无论是否可枚举。 更简单的原型语法
function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
但是这样,整个原型对象就没能自动获得constructor属性了。
var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true
可以手动添加,只是constructor的[[Enumerable]]特性就变为true了,可以使用Object.defineProperty(...)处理。
function Person(){
}
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
//重设构造函数,只适用于 ECMAScript 5 兼容的浏览器
Object.defineProperty(Person.prototype, "constructor", {
enumerable: false,
value: Person
}); 原型的动态性
function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error
对原型的修改会影响在修改之前已经创建好的实例。friend的__proto__属性指向的还是原来的原型对象。
再通过friend instanceof Person 来判断时,结果是false. 原型对象的问题
function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
friends : ["Shelby", "Court"], // 引用类型
sayName : function () {
alert(this.name);
}
};
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true
修改引用类型的值会反映到所有实例中。 组合使用构造函数模式和原型模式 (广泛使用)
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性 动态原型模式 (非常完美)
function Person(name, age, job){
//属性
this.name = name;
this.age = age;
this.job = job;
//方法
if (typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
};
}
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); 寄生构造函数模式
function Person(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
建议在可以使用其他模式的情况下,不要使用这种模式 稳妥构造函数模式
function Person(name, age, job){
//创建要返回的对象
var o = new Object();
//可以在这里定义私有变量和函数
//添加方法
o.sayName = function(){
alert(name);
};
//返回对象
return o;
}
var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
一是新创建对象的实例方法不引用 this;二是不使用 new 操作符调用构造函数。 继承
原型链
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true 借用构造函数 (也叫做伪造对象或经典继承)
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){
//继承了 SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors); //"red,blue,green" 组合继承 (最常用的继承模式)
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
使用原型链实现对原型的属性和方法的继承,使用构造函数实现对实例属性的继承。 原型式继承
function object(o) {
function F(){};
F.prototype = o;
return new F();
}
本质上object()对传入的对象进行了一次浅复制。
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
存在引用类型问题
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
ECMAScript 5 新增的Object.create 功能与object()类似。 寄生式继承
function createAnother(original){
var clone = object(original); //通过调用函数创建一个新对象
clone.sayHi = function(){ //以某种方式来增强这个对象
alert("hi");
};
return clone; //返回这个对象
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"
新增了自己的方法(sayHi),这种模式函数不能进行复用,每个实例都有自己的副本。 寄生组合式继承 (引用类型最理想的继承范式)
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
} function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType); //使用寄生组合模式,这样不必调用SuperType的构造函数
SubType.prototype.sayAge = function(){
alert(this.age);
};
整个过程只要调用一次SuperType的构造函数,而组合继承模式要调用两次,会在SubType.prototype创建不必要的属性。 typeof 判断基本类型
var result = typeof variable;
result
undefined, boolean, string, number, object, function
注:null --> Object instanceof 判断引用类型
var result = variable instanceof constructor;
result
true, false
alert(person instanceof Object); // 变量 person 是 Object 吗?
alert(colors instanceof Array); // 变量 colors 是 Array 吗?
alert(pattern instanceof RegExp); // 变量 pattern 是 RegExp 吗? instanceof通过判断对象沿着原型链能否找到类型的prototype属性指向的原型对象。 作用域链与原型链
var name = 'window';
var age = '1';
function Person(name, age) {
this.age = age;
this.sayName = function(greet) {
var sex = 'male';
//person1.sayName()调用时,会形成三个作用域,使用Chrome跟踪可以看到,分别是:Local, Closure, Global.
//在Local中有greet, sex, this, 三个变量, Closure有name变量,Global中也有name变量。
//当直接访问某一个变量名时,代码会沿着Local, Closure, Global的顺序查找
//比如greet是在Local中找到,name在Closure中找到
//当要在方法中访问this.age时,这时候,才是在Local的this变量中,沿着this对象的原型链进行查找。
alert(greet + ' ' + name);
alert(this.age);
alert(arguments[0]);
}
//测试多层作用域
this.sayName2 = function() {
var name2 = name;
return function() {
var sex = 'male';
alert(name2);
alert(this.age);
alert(arguments[0]);
}
}
}
// function Person(nameP, age) {
// this.age = age;
// this.name = nameP;
// this.sayName = function(greet) {
// var sex = 'male';
// alert(greet + ' ' + name);
// }
// } var person1 = new Person('Greg', 28);
var person2 = new Person('Nico', 29); person1.sayName('Hello');
var say2 = person1.sayName2();
say2();
//person1.sayName.call(this, 'Hi'); 作用域链看函数的[[Scope]]属性,函数在执行时,会添加本地作用域到作用域链前端。
在Chrome中作用域链体现为:Local--Closure(--Closure)--Global 严格模式 执行环境(execution context)、变量对象(variable object)、作用域链(scope chain) 垃圾收集
标记清除(mark-and-sweep)
引用计数(reference counting) 存在循环引用问题
解除引用(dereferencing)
variable = null; 通过这种方式解除循环引用和全局变量的引用(局部变量会在离开执行环境时自动被解除引用)。
解除引用的值,其内存会在垃圾收集器下次运行时回收。 //使用||操作符提供默认值backupObject.
var myObject = preferredObject || backupObject; '' null undefined 十进制 前导零 十六进制 数字+字符 字符
Number() 0 0 NaN 十进制 去掉 十进制 NaN NaN
parseInt() NaN NaN NaN 十进制 去掉 十进制 数字 NaN
parseFloat() NaN NaN NaN 十进制 去掉 0 数字 NaN parseInt 可以指定转换的进制,当指定了进制时,会按指定的进制解析字符串。 for (property in expression) statement;
通过for-in循环输出的属性名的顺序是不可预测的,所有的属性都会被返回一次,但先后顺序不同浏览器可能会有差异。 switch (expression) expression可以是任何数据类型,比较时使用的时全等(===)比较。 function (arg0, arg1...) {
statements;
}
函数命名的参数只是提供便利,并不是必须的。
函数的参数由arguments对象保存,它是一个类似数组的对象(并不是Array的实例),它的值的数量取决于调用函数时传递的参数数量,
而不取决于函数定义时命名的参数数量。
没有传递值的命名参数将自动被赋予undefined值。
不存在函数签名的特性,因此函数没有重载,后定义的会覆盖前面定义的同名函数。可以在函数内部,
通过arguments,取得传入参数的数量和类型,进而实现类重载功能。
返回值没有类型限定,同一个函数可以有多种类型的返回值。
函数名本身就是变量,指向一个函数对象。 函数声明与函数表达式
函数声明存在 函数提升
//不要这样做!
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
函数表达式
//可以这样做
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
} 递归
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); //出错!
factorial不在是函数了,所以报错
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
使用arguments.callee,但是在严格模式下不能访问arguments.callee
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});
使用函数表达式,这样f始终存在。 闭包
指有权访问另一个函数作用域的变量的函数。
闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,同时还有可能导致内存泄漏。 函数声明 --> 函数表达式
(function(){
//这里是块级作用域
})();
定义一个匿名函数,然后立即执行,这样在函数内部形成了一个块级作用域,
在这个作用域内可以声明任意变量而不用担心与全局作用域里的变量冲突。 私有变量
function MyObject(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特权方法
this.publicMethod = function (){
privateVariable++;
return privateFunction();
};
}
静态私有变量
(function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//构造函数
MyObject = function(){
};
//公有/特权方法
MyObject.prototype.publicMethod = function(){
privateVariable++;
return privateFunction();
};
})();
模块模式
var singleton = function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特权/公有方法和属性
return {
publicProperty: true,
publicMethod : function(){
privateVariable++;
return privateFunction();
}
};
}();
增强模块模式 (可以知道singleton的具体类型)
var singleton = function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//创建对象
var object = new CustomType();
//添加特权/公有属性和方法
object.publicProperty = true;
object.publicMethod = function(){
privateVariable++;
return privateFunction();
};
//返回这个对象
return object;
}(); 事件
事件冒泡,事件捕获
"DOM2级事件"规定的事件流:事件捕获阶段、处于目标阶段和事件冒泡阶段。
DOM0级事件处理程序:domObj.onXXX = function() {...}; 移除:onXXX = null;
DOM2级事件处理程序:
domObj.addEventListener("XXX", function() {...}, true/false);
true:捕获阶段调用事件处理程序;false:冒泡阶段调用事件处理程序。
移除:domObj.removeEventListener("XXX", handler, true/false);
remov...参数必须以add参数一样,因此处理函数必须定义到一个变量,匿名函数无法被移除。
IE事件处理程序:(冒泡阶段调用处理程序)
domObj.attachEvent("onXXX", function() {...});
移除:domObj.detachEvent("onXXX", handler); 资料
YUI http://developer.yahoo.com/yui/
基于Canvas的图像过滤器:http://www.html5rocks.com/en/tutorials/canvas/imagefilters/
webgl学习:http://learningwebgl.com/blog/?page_id=1217
http://www.hiwebgl.com/?p=42 */ /**
* 跨浏览器的事件处理程序
*/
var EventUtil = {
addHandler: function(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
getEvent: function(event) {
return event ? event : window.event;
},
getTarget: function(event) {
return event.target || event.srcElement;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
removeHandler: function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) {
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
stopPropagation: function(event) {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
}; /**
* 自定义事件
*/
function EventTarget() {
this.handlers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
addHandler: function(type, handler) {
if (typeof this.handlers[type] == "undefined") {
this.handlers[type] = [];
}
this.handlers[type].push(handler);
},
fire: function(event) {
if (!event.target) {
event.target = this;
}
if (this.handlers[event.type] instanceof Array) {
var handlers = this.handlers[event.type];
for (var i = 0, len = handlers.length; i < len; i++) {
handlers[i](event);
}
}
},
removeHandler: function(type, handler) {
if (this.handlers[type] instanceof Array) {
var handlers = this.handlers[type];
for (var i = 0, len = handlers.length; i < len; i++) {
if (handlers[i] === handler) {
break;
}
} handlers.splice(i, 1);
}
}
} var DragDrop = function() {
var dragdrop = new EventTarget(),
dragging = null;
diffX = 0;
diffY = 0; function handleEvent(event) { event = EventUtil.getEvent(event);
var target = EventUtil.getTarget(event); switch(event.type) {
case "mousedown":
if (target.className.indexOf("draggable") > -1 ) {
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
dragdrop.fire({type: "dragstart", target: dragging,
x: event.clientX, y: event.clientY});
}
break;
case "mousemove":
if (dragging !== null) {
dragging.style.left = (event.clientX - diffX) + "px";
dragging.style.top = (event.clientY - diffY) + "px";
dragdrop.fire({type: "drag", target: dragging,
x: event.clientX, y: event.clientY});
}
break;
case "mouseup":
if (dragging !== null) {
dragdrop.fire({type: "dragend", target: dragging,
x: event.clientX, y: event.clientY});
dragging = null;
} break;
} } dragdrop.enable = function() {
EventUtil.addHandler(document, "mousedown", handleEvent);
EventUtil.addHandler(document, "mousemove", handleEvent);
EventUtil.addHandler(document, "mouseup", handleEvent);
}; dragdrop.disable = function() {
EventUtil.removeHandler(document, "mousedown", handleEvent);
EventUtil.removeHandler(document, "mousemove", handleEvent);
EventUtil.removeHandler(document, "mouseup", handleEvent);
}; return dragdrop;
}(); DragDrop.addHandler("dragstart", function(event) {
var status = document.getElementById("status");
status.innerHTML = "Started dragging " + event.target.id;
});
DragDrop.addHandler("drag", function(event) {
var status = document.getElementById("status");
status.innerHTML += "<br/> Dragged " + event.target.id + " to (" + event.x +
", " + event.y + ")";
});
DragDrop.addHandler("dragend", function(event) {
var status = document.getElementById("status");
status.innerHTML += "<br/> Dropped " + event.target.id + " at (" + event.x +
", " + event.y + ")";
});
DragDrop.enable();

JavaScript -- JavaScript高级程序设计的更多相关文章

  1. JavaScript DOM高级程序设计 7.向应用程序加入Ajax--我要坚持到底!

    有时候,或许是因为理解能力,也或许是因为浮躁,看东西总是不入心,而且还老是想跳过本节,或者赶紧看完本节,这样的恶性循环,让我在即没有真正的学习到知识,又打击我的学习信心,还浪费了我很多事件,我想,当遇 ...

  2. JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    一.事件流 我们通过下面一个实例,进行说明. <body> <h1>Event Flow</h1> <ul id="nav"> &l ...

  3. JavaScript DOM高级程序设计 3.6 实例 将HTML代码转换成DOM代码(附源码)--我要坚持到底!

    作为一名Web开发者,最讨厌的事情就是重复性任务,摆脱乏味的日常重复性事物的一种方法,是借助可重用的对象或者说与你现在建立的ADS库类似的库,另外一种让事情变得有意思,且能够加速开发进程的方式是编写能 ...

  4. JavaScript DOM高级程序设计 3.-DOM2和HTML2--我要坚持到底!

    由一个HTML进行说明,我就不敲了,直接copy <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " ...

  5. JavaScript DOM高级程序设计2.1创建可重用的对象--我要坚持到底!

    1.对象中包含什么 在javascript中,从函数到字符串实际上都是对象 继承 //创建一个person对象的实例 var penson={}; person.getName=function(){ ...

  6. JavaScript DOM高级程序设计1.2-循序最佳实践--我要坚持到底!

    我这人,最大的毛病就是浮躁. 下面开始我再一次的学习之旅,希望我能坚持到最后.记笔记除了分享以外,更重要的是让自己看见自己学习之路. 先把ADS库贴出来http://vdisk.weibo.com/s ...

  7. JavaScript DOM 高级程序设计读书笔记二

    响应用户操作和事件 事件就是操作检测与脚本执行的组合,或者基于检测到的操作类型在某个对象上调用事件侦听器(事件处理程序). 事件的类型 事件可以分为几种类型:对象事件,鼠标事件,键盘事件(只适用于do ...

  8. JavaScript DOM 高级程序设计读书笔记一

    创建可重用的对象 简而言之,对象就是包含一组变量(称为属性)和函数(称为方法)的集合的实例.对象通常由类派生而来,而类中定义了对象拥有的属性和方法.如果你的脚本中都是对象之间的交互操作,那么就可以称之 ...

  9. 《JavaScript》高级程序设计第21章:Ajax和Comet,jsonp

    一.创建XMLHttpRequest对象 二.XHR的用法 五.跨域资源共享 六.其他跨域技术七.安全七.安全 1. 图像Ping 2. JSONP(JSON with padding,填充式JSON ...

  10. 《javascript》高级程序设计——类型转换错误

    容易发生类型转换错误的另一个地方,就是流控制语句.像if之类的语句在确定下一步操作之前,会自动把任何值转换成布尔值.尤其是if语句,如果使用不当,最容易出错.来看下面的例子. function con ...

随机推荐

  1. 基于Socket创建Web服务

    基于Socket创建Web服务 为什么要使用Socket呢,我们来看下图

  2. android开发过程遇到的一些错误

    Unable to resolve target "android-x" 这是工程的Android版本和本地SDK中的版本不一致,一般做下处理: 1. 右击项目->andro ...

  3. Scrapy学习-21-信号量

    scrapy信号量 定义 Scrapy使用信号来通知事情发生.您可以在您的Scrapy项目中捕捉一些信号(使用 extension)来完成额外的工作或添加额外的功能,扩展Scrapy. 虽然信号提供了 ...

  4. PHP安装oracle的php_oci和oci8扩展

    环境:centos6.9 php5.3.3 oracle客户端:下载链接:http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277 ...

  5. centos7下mysql双主+keepalived

    一.keepalived简介 keepalived是vrrp协议的实现,原生设计目的是为了高可用ipvs服务,keepalived能够配置文件中的定义生成ipvs规则,并能够对各RS的健康状态进行检测 ...

  6. 搜狗拼音输入法LINUX版安装

    搜狗拼音输入法LINUX版官方下载: http://pinyin.sogou.com/linux/?r=pinyin 一.添加fcitx的nightlyPPA 在终端中输入: sudo add-apt ...

  7. DB2 数据库中字段特定字符替换为空

    Update RM_CarInfo set ImportTitle = Replace(ImportTitle,'ZD','') WHERE ImportTitle LIKE'%ZD%';

  8. json手动解析详解

    项目中有时候仅仅需要一个或者多个字段时可以使用这种解析方式,省去创建实体类. 1.首先讲解下最基本的数据格式. 例如: String json="{'name':'小明','action': ...

  9. Codeforces 912D Fishes (概率&期望,优先队列的应用)

    题目链接 Fishes 题意  在一个$n*m$的矩阵中,随机选择一个$r * r$的区域覆盖. 一开始我们可以在这个$n*m$的矩阵中选择$k$个点标记为$1$. 我们要选择一个最佳的标记策略,使得 ...

  10. LAN、WAN、WLAN的区别

    听语音 浏览:22034 | 更新:2015-06-22 20:10 | 标签:网线 1 2 3 4 5 6 7 分步阅读 好多朋友在群内问我路由器如何配置,本来还耐心解答,但是他竟然连LAN.WAN ...