获取隐藏元素的宽度

问题描述

如果DOM元素的fu’yu是被隐藏的(display: none),那么无论使用DOM的接口,还是jquery的接口来获取该元素的宽度,得到的结果始终是0. 例如:

 
 
<div id="node">
  <p>
    hello world
  </p>
</div>
 
 
#node {
    display: none;
}
 
 
alert($('#node p').width());

解决方法

在过去元素的宽度之前,临时修改元素的display为block,获取之后再讲其设置回none

例如:

 
 
function get_width(obj) {
  var width = 0;
  obj.parent().css('display', 'block');
  width = obj.width();
  obj.parent().css('display', 'none');
  return width;
}
alert(get_width($('#node p')));

给jquery添加一个函数

参考StackOverflow ,Tim Banks给jquery添加了一个函数,用来获取隐藏元素的宽度和高度信息。

 
 
(function ($) {
$.fn.getHiddenDimensions = function (include_margin) {
    var $item = this,
    props = { position: 'absolute', visibility: 'hidden', display: 'block' },
    dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
    $hiddenParents = $item.parents().addBack().not(':visible'),
    includeMargin = (include_margin == null) ? false : include_margin;
    var oldProps = [];
    $hiddenParents.each(function () {
        var old = {};
        for (var name in props) {
            old[name] = this.style[name];
            this.style[name] = props[name];
        }
        oldProps.push(old);
    });
    dim.width = $item.width();
    dim.outerWidth = $item.outerWidth(includeMargin);
    dim.innerWidth = $item.innerWidth();
    dim.height = $item.height();
    dim.innerHeight = $item.innerHeight();
    dim.outerHeight = $item.outerHeight(includeMargin);
    $hiddenParents.each(function (i) {
        var old = oldProps[i];
        for (var name in props) {
            this.style[name] = old[name];
        }
    });
    return dim;
}
}($));
alert($('#node p').getHiddenDimensions().width);

在jsFiddle上试一试 ->

ES6: 模块编程

Javascript模块的限制

  • 只能运行于严格模式
  • 模块中的顶级作用域中的变量,不会被自动添加到全局作用域
  • 顶级作用域的this为undefined

导出

如果想让模块中的变量、函数、类被其他模块使用,需要将其导出,导出的方法如下:

  • export var color = “red”;
  • export function print_hello(){};
  • export { print_hello }
  • export { print_hello as printh };
  • export default function print_hello(){};
  • export default print_hello
  • export { print_hello as default}

导入

如果想使用其他模块中的变量、函数、类,需要将其导入。导入后的变量、类、函数为只读。导入的方法如下:

  • import { color, print_hello } from “./example.js”;
  • import * as example from “./example.js”;  //example.color, example.print_hello
  • import { print_hello as printh } from “./example.js”;
  • import print_hello, { color } from “./example.js”; // print_hello 为默认导出的函数
  • import { default as printh } from “./example.js”;

ES6:数组

新增的静态方法

Array.of() :可以将传入的参数逐个传入数组,即使只有一个数值类型的参数,也会成为新数组的成员,而不是代表数组的长度

Array.from():可以将类数组结构转化为数组,例如: Array.from(arguments). 利用Array.from()也可以转换原来的数组,例如:

 
 
  1. let trans_args = function() {
  2. let args = Array.from(arguments, (value)=>value + 1);
  3. console.log(args);
  4. }
  5. trans_args(1, 2, 3);
  6. $ node test.js
  7. [ 2, 3, 4 ]

新增的普通方法

find() 与findIndex():传入一个回调函数来表明查找的条件,例如:

 
 
> let arr = [1, 2, 3, 4, 5];
undefined
> arr.find((n)=>n>3);
4
> arr.findIndex((n)=>n>3);
3

fill(value, start, end):填充value到数组的start到end位置,不包括end. 例如:

 
 
let arr = [1, 2, 3, 4, 5];
arr.fill(1, 1, 4);
[ 1, 1, 1, 1, 5 ]

copyWithin(toIndex, fromIndex, stopIndex): 从fromIndex开始复制元素到toIndex,遇到stopIndex停止,例如:

 
 
> let arr = [1, 2, 3, 4, 5]
undefined
> arr.copyWithin(2, 0, 1);
[ 1, 2, 1, 4, 5 ]

类型化数组

javascript中的数组缓冲区类似于c的malloc,例如,可以用如下方法分配一个10个字节大小的内存区域:

 
 
> let bu = new ArrayBuffer(10);
undefined
> bu.byteLength
10

可以使用slice(start, end)方法来对分配的内存进行切片。

要操作新分配的内存,需要使用DataView(buf, index, length)创建一个视图,例如:

 
 
> let buf = new ArrayBuffer(50);
> let view = new DataView(buf, 0, 50);

获取视图的信息:

 
 
> view.buffer === buf;
true
> view.byteOffset
0
> view.byteLength
50

读写数据:

 
 
> view.setUint8(4, 233);
undefined
> view.getUint8(4)
233

ES6中的类

ES6中添加的class关键字其实并非真正的类,而是ES5用函数来模拟类的语法糖。在ES6中可以用如下的语法创建一个类:

 
 
class Students {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName() {
        console.log(this.name);
    }
    sayAge() {
        console.log(this.age);
    }
}
let st1 = new Students('sen', 18);
st1.sayName();
st1.sayAge();

使用ES6的class语法糖和ES5自定义的类还是有些区别的:

  • 类的声明不会被提升,类的实例化只能在类的声明之后
  • 类声明中的代码只能运行在严格模式下
  • 类中的方法是不可枚举的
  • 实例化的时候必须加new关键字
  • 在方法内部修改类名会抛出错误,但可以在外部修改类名

下面的例子展示了如何在外部修改类名:

 
 
class Students {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName() {
        console.log(this.name);
    }
    sayAge() {
        console.log(this.age);
    }
}
let st1 = new Students('sen', 18);
st1.sayName();
st1.sayAge();
let Stu = Students;
let st2 = new Stu('sen', 18);
st2.sayName();
st2.sayAge();
console.log(st1 instanceof Students); //true
console.log(st2 instanceof Students); //true
console.log(st2 instanceof Stu); //true
console.log(st1 instanceof Stu); //true

类中的访问器属性

可以使用get和set关键字来定义访问器属性,例如:

 
 
class Students {
    constructor(name) {
        this.name = name;
    }
    get n() {
        return this.name;
    }
    set n(value) {
        this.name = value;
    }
}
let st1 = new Students('sen', 18);
console.log(st1.n);
st1.n = 'wang';
console.log(st1.n);

需计算的属性名

和其他需计算的名字一样,都是加上方括号,例如:

 
 
let propName = "sayName";
class Students {
    constructor(name) {
        this.name = name;
    }
    [propName]() {
        console.log(this.name);
    }
}
let st1 = new Students('sen');
st1.sayName();

给类添加默认的生成器

可以利用Symbol来给类添加默认的生成器,如:

 
 
class Collection {
    constructor() {
        this.items = [];
    }
    *[Symbol.iterator]() {
        yield *this.items.values();
    }
}
let col = new Collection();
col.items.push(1);
col.items.push(2);
col.items.push(3);
for( let i of col) {
    console.log(i);
}

给类添加静态属性/方法

类的静态方法/属性只能通过类名来访问,而不能通过类的实例来访问,具体做法是在方法/属性定义前面加上static关键字,例如:

 
 
class Students {
    constructor(name) {
        this.name = name;
    }
    static sayClassName() {
        console.log("Collection");
    }
}
Students.sayClassName();
let stu = new Students('sen');
stu.sayClassName(); // error

类的继承

ES6引入了extends和super来实现类的继承,例如:

 
 
class Rectangle {
    constructor(length, width) {
        this.length = length;
        this.width = width;
    }
    getArea() {
        return this.length * this.width;
    }
}
class Square extends Rectangle {
    constructor(length) {
        super(length, length);
    }
}
let sq = new Square(5);
console.log(sq.getArea());

使用super需要注意:

  • super只能用在派生类中
  • 在constructor里,super负责初始化this,所以必须在this使用之前调用

ES6: 迭代器与生成器

什么是迭代器?

迭代器是一个对象,它拥有一个next方法,调用next方法会返回一个对象,该对象有两个属性值,value和done。每次调用next方法,返回的value表示可迭代对象中的下一个值,done表示迭代是否完成。根据此定义,可用下面的代码实现一个迭代器:

 
 
let create_iter = function(items) {
    let i = 0;
    return {
        next: function() {
            let value, done;
            if (i >= items.length) {
                value = null;
                done = true;
            } else {
                value = items[i++];
                done = false;
            }
            return {
                value: value,
                done: done
            }
        }
    }
}

什么是生成器?

用来创建迭代器的函数称之为生成器,ES6为了简化生成器,引入了新的语法:

  • 在生成器函数前加*
  • 使用yield关键字抛出下一个value

引入新的语法后,生成器的代码可以简化为:

 
 
let gen = function*(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
}

举个栗子

下面的代码比较了两种创建迭代器的方法:

 
 
let create_iter = function(items) {
    let i = 0;
    return {
        next: function() {
            let value, done;
            if (i >= items.length) {
                value = null;
                done = true;
            } else {
                value = items[i++];
                done = false;
            }
            return {
                value: value,
                done: done
            }
        }
    }
}
let gen = function*(items) {
    for (let i = 0; i < items.length; i++) {
        yield items[i];
    }
}
let items = [1, 2, 3, 4, 5];
let it = gen(items);
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

输出结果:

 
 
$ node test.js 
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 4, done: false }
{ value: 5, done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }

生成器的表现形式

  • function *my_generator(items) {}
  • let my_generator = function *(items) {}
  • let obj = {*my_generator(items){}};

可迭代对象

可迭代对象指的是包含Symbol.iterator属性的对象,数组、Set、Map、字符串都是可迭代对象,都有默认的迭代器。

可迭代对象可以与for-of配合使用,例如:

 
 
let numbers = [1, 2, 3, 4, 5];
for (let num of numbers) {
    console.log(num);
}

可以用一下方法自定义一个可迭代对象:

 
 
let colors = {
    items: [1, 2, 3, 4, 5],
    *[Symbol.iterator]() {
        for (let item of this.items) {
            yield item;
        }
    }
}

内置迭代器

数组、Map和Set 都有一下三个内置的迭代器:

  • entries(): 返回一个包含键值对(数组)的迭代器
  • values(): 返回一个只包含值的迭代器
  • keys(): 返回一个只包含键的迭代器

对于数组来说,keys返回的是元素的下标,对于Set来说,返回的是元素的值,而对于Map来说,返回的是元素的key。

给迭代器传入参数

当调用next方法时,若传入参数,则该参数会替代上一次yield表达式的值,例如:

 
 
let gen = function *() {
    let a = yield 1;
    let b = yield a + 1;
    yield b + 1;
}
let iter = gen();
console.log(iter.next());
console.log(iter.next(100));
console.log(iter.next(200));
console.log(iter.next());

执行结果:

 
 
$ node test.js 
{ value: 1, done: false }
{ value: 101, done: false }
{ value: 201, done: false }
{ value: undefined, done: true }

生成器委托

也就是生成器的嵌套,例如:

 
 
let generator0 = function *() {
    yield 0;
    yield 1;
    yield 2;
}
let generator1 = function *() {
    yield 3;
    yield 4;
    yield 5;
}
let generator = function *() {
    yield *generator0();
    yield *generator1();
    yield 6;
}
let iter = generator();
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());
console.log(iter.next());

ES6: Set 与 Map

Set

  • let my_set = new Set();
  • let my_set = new Set([1, 1, 2, 2]);
  • my_set.add(5);
  • my_set.delete(5);
  • my_set.has(5);
  • my_set.forEach(function(value){});
  • let my_set = WeakSet() // 只允许对象作为set的元素,便于垃圾回收

Map

  • let my_map = new Map();
  • let map = new Map([[“name”, “Nicholas”], [“age”, 25]]);
  • my_map.set(key, value);
  • my_map.get(key)
  • my_map.has(key)
  • my_map.delete(key);
  • my_map.clear();
  • my_map.size;
  • my_map.forEach(function(value, key, ownerMap) {
    console.log(key + ” ” + value);
    console.log(ownerMap === map);
    });
  • let map = new WeakMap();

ES6: 符号类型

引入原因:

  • 实现私有属性
     
     
    let s = Symbol()
    let obj = {[s]: 'hello world'};
    console.log(obj.s); //undefined
  • 符号值唯一
     
     
    let s = Symbol()
    let m = Symbol()
    console.log(s === m)

创建:

  • 不能用字面量形式创建
  • 使用Symbol(desc)函数创建,不需要添加new
  • Symbol.for(key)在全局符号注册表中查找key符号值,如果找到就返回,没找到就创建一个新的符号值
  • Symbol.keyFor(symbol): 返回符号值的key

枚举:

  • 符号类型的key是不能被枚举的,Object.keys()以及Object.getOwnPropertyNames()都不能返回符号类型的key
  • Object.getOwnPropertySymbols()则会返回对象中所有符号类型的key

共享符号值:

  • Symbol.for(desc): 在全局符号注册表中查找描述为desc的符号,如果找到,返回这个符号值,如果没有,则创建一个新的符号值并返回
  • Symbol.keyFor(var): 返回全局符号注册表中符号值为var的desc.

转换:

  • 不能强制转化为字符串或者数值类型, 所以 symbol + “hello” 或者 symbol/1 会报错
  • 可以调用String()来转换

知名符号:

  • Symbol.hasInstance(obj): 判断obj是不是但前函数的实例,如Array[Symbol.hasInstance](obj); 可以通过以下代码改变instanceof的默认行为:
     
     
        Object.defineProperty(MyObject, Symbol.hasInstance, {
            value: function(v) {
                return false;
            }
        });
  • Symbol.isConcatSpreadable
     
     
    let collection = {
    0: "Hello",
    1: "world",
    length: 2,
    [Symbol.isConcatSpreadable]: true
    };
    let messages = [ "Hi" ].concat(collection);
    console.log(messages.length); // 3
    console.log(messages); // ["hi","Hello","world"]
  • Symbol.match 、 Symbol.replace 、 Symbol.search 、Symbol.split
  • Symbol.toPrimitive
     
     
    function Temperature(degrees) {
        this.degrees = degrees;
    }
    Temperature.prototype[Symbol.toPrimitive] = function(hint) {
        switch (hint) {
        case "string":
            return this.degrees + "\u00b0"; // 温度符号
        case "number":
            return this.degrees;
        case "default":
            return this.degrees + " degrees";
        }
    };
    let freezing = new Temperature(32);
    console.log(freezing + "!"); // "32 degrees!"
    console.log(freezing / 2); // 16
    console.log(String(freezing)); // "32°"
  • Symbol.toStringTag
     
     
    > age[Symbol.toStringTag] = 'Node';
    'Node'
    > age
    { age: 32,
    [Symbol(Symbol.toPrimitive)]: [Function],
    [Symbol(Symbol.toStringTag)]: 'Node' }
    > age.toString();
    '[object Node]'

ES6: 对象和数组解构

所谓解构,指的是将数据结构分解为更小的部分,从而使数据提取变得容易。

对象解构:

  • 使用解构时,必须提供初始化值

    [code lang=”js” collapse=”false”]
    let Person = {
    name: ‘sen’,
    age: 18
    }
    let {name, age} = Person;
    [/code]

  • 解构表达式的值为=右侧的值
  • 如果对象中没有同名属性时,解构表达式新赋值的变量的值为undefined
  • 解构对象只是赋值时,需要加()
  • 赋值给不同名的变量

    [code lang=”js” collapse=”false”]
    let Person = {
    name: ‘sen’,
    age: 18
    }
    let {name: localName, age: localAge} = Person;
    [/code]

  • 设置默认值

    [code lang=”js” collapse=”false”]
    let Person = {
    name: ‘sen’,
    age: 18
    }
    let {name, age: localAge = 18} = Person;
    [/code]

  • 嵌套解构

    [code lang=”js” collapse=”false”]
    let Person = {
    name: ‘sen’,
    age: 18,
    score: {
    maths: 100
    }
    }
    let {name, score: {maths}} = Person;
    console.log(maths);
    [/code]

数组解构

  • [code lang=”js” collapse=”false”]
    let score = [99, 88, 77];
    let [maths, english, chinese] = score;
    [,,chinese] = score;
    [/code]
  • 数组解构赋值不需要加()
    [code lang=”js” collapse=”false”]
    let a = 3;
    let b = 4;
    [a, b] = [b, a]
    [/code]
  • 嵌套的解构
    [code lang=”js” collapse=”false”]
    let score = [99, 88, [77]];
    let [,,[chinese]] = score;
    [/code]
  • 剩余项
    [code lang=”js” collapse=”false”]
    let score = [99, 88, 77];
    let [maths, …restScore] = score;
    console.log(restScore) // [88, 77]
    [/code]
  • 数组和对象可以混合解构
    [code lang=”js” collapse=”false”]
    let Person = {
    name: ‘sen’,
    age: [0, 18]
    }
    let {name: localName, age: [start]} = Person;
    console.log(start);
    [/code]

ES6: 对象扩展

  • 初始化简写:

    [code lang=”js” collapse=”false”]
    function createPerson(name, age) {
    return { name: name, age: age };
    }
    —&amp;amp;amp;amp;gt;
    function createPerson(name, age) {
    return { name, age };
    }

    [/code]

  • 方法简写:

    [code lang=”js” collapse=”false”]
    var person = {
    name: "sen",
    sayName: function() {
    return this.name;
    }
    }
    —&amp;amp;amp;gt;
    var person = {
    name: "sen",
    sayName() {
    return this.name;
    }
    }
    [/code]

  • 需要计算的属性名用[]表示
  • Object.is() 与===表现相同,除了
    Object.is(NaN, NaN) // true
    Object.is(+0, -0) // false
  • Object.assign(target, source) 将source中的属性和方法混入target对象
  • 允许重发的属性定义,排在最后的为实际值
  • 属性枚举的顺序:
    • 所有数字类型的键按升序排列
    • 所有字符串类型的键按添加进对象的顺序排列
    • 所有符号类型的键也按照添加进对象的顺序排列
  • 可修改对象的原型:
    Object.setPrototypeOf(obj, new_prototype)
  • 使用super作为指向原型对象的指针

ES6: 函数扩展

  • 带默认值的函数:var get_name = function(url, id=1, callback){};
    • 如果传入了第二个参数,将不会使用默认值
    • 如果给第二个参数赋值为undefined,会使用默认值
    • 带有默认值的参数后,arguments的内容将不会随着形参的改变而改变
    • 排在后面的参数可以将前面的参数作为默认值,而前面的参数不能引用后面的参数作为默认值
  • 剩余参数:var get_name = function(url, …keys)
    • 除了第一个参数url外,剩余所有参数都会被放到keys数组中
    • 函数只能有一个剩余参数,且必须放到最后
    • 剩余参数不能再对象字面量的setter属性中使用
  • 延展运算符:var args = [‘url’, 123, ‘st’]; get_names(…args);
  • new.target: 使用new创建一个对象时,会被赋值为新对象的构造器
  • ES6允许在代码块中定义函数,在严格模式中,块级函数只能在块级作用域中使用,而非严格模式中,块级函数会被提升到全局
  • 箭头函数
    • 没有this,super,arguments,new.target,这些值由所在的、最靠近的非箭头函数来决定
    • 不能使用new来调用
    • 没有原型
    • 不能更改this
    • 不允许有重复的具名参数
    • 语法
      • var reflect = value => value;
      • var sum = (num1, num2) => num1 + num2;
      • var getName = () => ‘Nicholas’;
      • var sum = (num1, num2) => {return num1 + num2};
      • var doSomething = () => {};
      • var getItem = (id) => ({id: id, name: ‘Nicholas’});
      • var person = ((name) => {return {getName: function() {return name}};})(‘Nicholas’);
  • 尾调用优化:满足以下条件的尾调用将会被优化,在尾调用时不会创建新的栈帧,而是清除当前栈帧并再次利用它
    • 尾调用不能引用当前栈帧中的变量(意味着该函数不能是闭包)
    • 进行尾调用的函数在尾调用返回结果后不能做额外操作
    • 尾调用的结果作为当前函数的返回值

ES6: 字符串处理

UTF-16编码:

  • str.codePointAt(index)
  • String.fromCodePoint(codepoint);
  • normalize()

正则表达式

  • 新增u修饰符用来处理UTF-16编码的问题  /&.$/u
  • 新增pattern.flags 属性 // ‘ig’
  • 新增pattern.sticky 属性及’y’修饰符 // 只从lastIndex处匹配,如果和’g’一起存在则’g’被忽略
  • 复制正则表达式  // let pattern = new RegEX(old_pattern, ‘gi’)

字符串处理

  • str.includes(sub_string) // true or false
  • str.startsWith(sub_string)  // true or false
  • str.endsWith(sub_string) // true or false
  • str.repeat(times);  // str * times
  • 模板字面量
    • 支持多行字符串
    • 支持变量  // `hello ${name}`

Javascript中的表单

var form = document.getElementById(‘myform’);

  • form.acceptCharset 服务器能处理的字符集
  • form.action 接受请求的URL
  • form.elements 表单中的所有控件
  • form.enctype 编码类型
  • form.length 控件数量
  • form.method HTTP请求类型
  • form.name   // document.forms[form.name]
  • form.reset()
  • form.submit()
  • form.target

var text = form.elements[‘sex’];

  • text.disabled
  • text.form
  • text.name
  • text.value
  • text.readOnly
  • text.tabIndex
  • text.type
  • text.select()
  • text.setSelectionRange(start, end)
  • text.value.substring(text.selectionStart, text.selectionEnd)

text的事件:

  • change
  • focus
  • blur

剪贴板

var clipboard = window.clipboardData ; //event.clipboardData;

  • clipboard.getData()
  • clipboard.setData()
  • clipboard.clearData()

剪贴板事件

  • beforecopy
  • copy
  • beforecut
  • cut
  • beforepaste
  • paste

 

Javascript中的事件

事件捕获(capturing)和事件冒泡(bubbling)

添加事件处理程序的两种方法

  • <div onclick=”alert(‘ddd’)”></div>  // onclick=null
  • elem.addEventListener(“click”, e_func, false); //elem.removeEventListener(‘click’, e_func, false); //false 表明在冒泡阶段被触发

事件对象

  • e.bubbles // true or false 是否冒泡
  • e.cancelable // true of false 是否可取消默认行为
  • e.currentTarget // 正在处理事件的元素,事件处理程序中的this指向该元素
  • e.target // 事件发生的目标元素
  • e.defaultPrevented // true or false 默认行为是否被取消
  • e.detail
  • e.eventPhase // 1 捕获阶段 2 处于目标 3冒泡阶段
  • e.preventDefault()
  • e.stopImmediatePropagation() //阻止事件冒泡和所有事件处理程序
  • e.stopPropagation() //阻止事件冒泡
  • e.trusted // true 表示事件由浏览器生成,false表示有javascript触发
  • e.type
  • e.view
  • e.clientX e.clientY 事件发生时鼠标的视图位置
  • e.pageX e.pageY 事件发生时鼠标的页面位置
  • e.screenX e.screenY 事件发生时鼠标的屏幕位置
  • e.ctrlKey e.shiftKey e.altKey e.metaKey 事件发生时修饰键是否被按下
  • e.button // 0 主键 1 滚轮键 2右键 被按下
  • e.wheelDelta
  • e.charCode
  • e.keyCode
  • e.data //textinput 事件时输入的字符
  • e.iputMethod //0-9 输入来源,如键盘、粘贴、拖放等

事件类型

  • UI事件
    • load  (window, img)
    • unload
    • resize (window)
    • scroll (window)
  • 焦点事件
    • blur 失去焦点事触发,不会冒泡
    • focusin
    • focusout
    • focus 不会冒泡
  • 鼠标与滚轮事件
    • click
    • dbclick
    • mousedown 任何鼠标按键被按下时触发
    • mouseup
    • mouseenter 不冒泡
    • mouseover 冒泡
    • mousemove
    • mouseleave 不冒泡
    • mouseout 冒泡
    • mousewheel
    • contextmenu 鼠标右键弹出菜单
  • 键盘事件
    • keydown
    • keypress
    • keyup
    • textinput
  • DOM变动事件
    • DOMSubtreeModified
    • DOMNodeInserted
    • DOMNodeRemoved
    • DOMNodeInsertedIntoDocument
    • DOMNodeRemovedFromDocument
    • DOMAttrModified
    • DOMCharacterDataModified

事件委托和移除

为提升性能,利用事件冒泡来减少事件处理程序;在DOM元素被innerHTML移除后,需要手动的移除事件处理程序

事件模拟

  • var e = document.createEvent(‘MouseEvents’);
  • e.initMouseEvent(….);
  • elem.dispatchEvent(e);

DOM中的选择符API及元素遍历

选择符API

  • document.querySelector(css_selector)
    var checked_radio = document.querySelector(‘.checked’);
  • var node_list = document.querySelector(css_selector);
  • elem.matchesSelector(css_selector) // true or false

HTML 5中的类名操作

classList是DOMTokenList的实例,因而具有以下方法:

  • elem.classList.add(value); 如果已经有了就不添加了
  • elem.classList.contain(value) //true or false
  • elem.classList.remove(value)
  • elem.classList.toggle(value); 如果有就删除,如果没有就添加

 元素遍历

Element新增5个属性:

  • childElementCount: 子元素的个数(不包括Text和Comment类型)
  • firstElementChild
  • lastElementChild
  • previousElementSibling
  • nextElementSibling

Javascript中的DOM节点类型

Node类型

  • node.nodeType:
    • Node.ELEMENT_NODE(1);
    • Node.ATTRIBUTE_NODE(2);
    • Node.TEXT_NODE(3);
    • Node.CDATA_SECTION_NODE(4);
    • Node.ENTITY_PREFERENCE_NODE(5);
    • Node.ENTITY_NODE(6);
    • Node.PROCESSING_INSTRUCTION_NODE(7);
    • Node.COMMENT_NODE(8);
    • Node.DOCUMENT_NODE(9);
    • Node.DOCUMENT_TYPE_NODE(10);
    • Node.DOCUMENT_FRAGMENT_NODE(11);
    • Node.NOTATION_NODE(12);
  • node.nodeName: 标签名
  • node.childNodes[0]  node.childNodes.item(0);
  • node.childNodes.length;
  • node.parentNode;
  • node.nextSibling;
  • node.previousSibling;
  • node.firstChild;
  • node.lastChild;
  • node.appendChild(newNode);
  • node.insertBefore(newNode);
  • node.replaceChild(newNode, oldNode);
  • node.removeChild(node);
  • node.cloneNode(true//深复制)

HTMLDocument类型

  • document.nodeType = 9
  • document.nodeName = “#document”
  • document.nodeValue = null
  • document.parentNode = null
  • document.ownerDocument = null
  • document.firstChild === document.childNodes[0] === document.documentElement 都指向<html>元素
  • document.body指向<body>元素
  • document.head
  • document.charset
  • document.URL;
  • document.title;
  • document.domain;
  • document.getElementById();
  • document.getElementByClassName();
  • document.getElementsByTagName();
  • document.getElementsByName();
  • document.images;
  • document.anchors;
  • document.links;
  • document.forms;
  • document.createElement(‘div’)
  • document.activeElement: 指向获得焦点的元素
  • document.readyState // loading or complete

Element类型

var elem = document.getElementById(‘elem_id’);

  • elem.nodeType = 1
  • elem.nodeName 为元素的标签名
  • elem.nodeValue = null
  • elem.parentNode 为document或者Element
  • elem.nodeName === elem.tagName
  • elem.getAttribute(“id”)
  • elem.setAttribute(“id”, “new_id”)
  • elem.attributes.getNamedItem(‘id’)
  • elem.attributes.removeNamedItem(‘id’)
  • elem.attributes.setNamedItem(new_attr)
  • elem.getElementsByTagName()
  • elem.dataset // data- 前缀自定义的属性及属性值
  • elem.innerHTML // 元素的内容(所有子节点HTML)
  • elem.scrollIntoView() //将元素滚动至可见视图中
  • elem.style.width
  • elem.style

Text类型

<div>hello world</dev>

var text_node = div.firstChild;

var text_node = document.createTextNode(text);

  • text_node.nodeValue = text_node.data = ‘hello world’
  • text_node.appendData(‘string’);
  • text_node.deleteData(offset, count);
  • text_node.insertData(offset, text);
  • text_node.replaceData(offset, count, new_text);
  • text_node.splitText(offset);
  • text_node.substringData(offset);
  • text_node.length = text_node.data.length = text_node.nodeValue.length;
  • text_node.parentNode.normalize() // 将两个子文本节点合并

Comment类型

<div id=’mydiv’><!– comment –></div>

var mydiv = document.getElementById(‘mydiv’);

var comment = mydiv.firstChild;

var comment = document.createComment(‘comment’);

  • comment类型和Text类型继承自同一个基类,拥有除splitText之外Text的所有属性和方法

Attr类型

elem.attributes中的节点

var attr = document.createAttribute(attr_name);

  • attr.nodeType = 11
  • attr.nodeName 属性名
  • attr.nodeValue 属性值
  • attr.parentNode = null
  • elem.setAttributeNode(attr);

Javascript中的location对象

  • window.location === document.location // true
  • location的属性列表
  • 修改location的属性会导致页面刷新并产生新的历史记录
  • window.location = “URL” 和 location.href=”URL”效果一样,都会调用location.assign(URL)
  • location.replace(URL)不会产生新的历史记录,而且会禁用后退
  • location.reload(true): 重新加载页面,参数可以选择是否从服务器加载(而不是从缓存加载)

Javascript中的window对象

window对象的两个作用:

  • 表示浏览器的一个实例
  • ECMAscript中的Global对象
    直接定义Global变量与在window上定义Global变量的区别是:直接定义的Global变量的[[configurable]]特性为false,也就是说,它不能用delete删除

窗口关系及框架

  • 如果html中包含框架(frame),那么每个框架都有自己的window对象,它们从上到下,从左到右,依次存放于window.frames数组中。可以通过window.frames[index]或者window.frames[frame_name]来获取frame的window对象
  • window.name为frame的name
  • top对象表示最外层html的window对象
  • parent对象表示上层frame的window对象
  • self表示frame自身的window对象

窗口位置

  • window.screenLeft window.screenTop 或者firefox中的window.screenX window.screenY表示窗口左上角的位置
     
     
        var left = (typeof window.screenLeft == "number") ? window.screenLeft: window.screenX;
        var top = (typeof window.screenTop == "number") ? window.screenTop: window.screenY;
       
  • window.outerHight window.outerWidth 表示窗口的高和宽
  • window.innerHight window.innerWidth 表示页面视图的高和宽

打开新窗口

  • window.open(URL, target, args, is_replace)
    URL: 新窗口打开的网址
    target: 目标frame的名字,或者_self, _parent,_top,_blank
    args: is_replace: 是否替代当前窗口
  • window.close() : 关闭一个窗口
  • window.closed: 布尔值,window是否已经关闭
  • window.opener: 表示打开本窗口的窗口window对象

超时调用与间歇调用

  • var id = setTimeout(function, ms)  ; clearTimeout(id);
  • var id = setInterval(function, ms) ; clearInterval(id);

系统对话框

  • alert(‘string’)
  • var boolean = confirm(“string”);
  • var result_string = prompt(“string”, “default_answer”);
"