JS红宝书·读书笔记 -- 上篇

JS红宝书·读书笔记 -- 上篇_第1张图片
JavaScript 高级程序设计

个人博客:https://yeaseonzhang.github.io

花了半个多月的时间,终于又把“JS红宝书”又撸了一遍。

第一次读“JS红宝书”还是2015年初学JS的时候,那时候只是把语法部分读了一遍,还有一些浏览器相关知识做了下了解,大概也就读了半本的样子,
就开始了用JS进行开发了,在成长的道路上遇见了JQuery,当时真的是感觉到JQuery太友好了,慢慢放下了原生开发。

现在呢,更多的时候是在用框架进行开发,越来越觉得自己的JS基础很缺乏,然后就开启了“JS红宝书”二刷之路。

下面就把书中自己觉得重要的、没有掌握的知识整理出来。因为我觉得还是会三刷“JS红宝书”,希望把这本700多页的书越读越薄,勉励。

章节

  • 在HTML中使用JavaScript
  • 基本概念
  • 变量、作用域和内存问题
  • 引用类型
  • 面向对象的程序设计
  • 函数表达式
  • BOM
  • DOM
  • DOM 扩展
  • DOM2 和 DOM3

在HTML中使用JavaScript


async

加载外部脚本文件,通知浏览器立即下载,异步执行。

noscript 元素

noscript标签显示条件:

  • 浏览器不支持脚本
  • 浏览器支持脚本,但是脚本被禁用

基本概念


语法

标识符

  • 第一个字符必须是一个字母、下划线或者一个美元符号
  • 其他字符可以是字母、下划线、美元或者数字

严格模式

支持严格模式的浏览器包括:IE10+、Firefox4+、Safari 5.1+、Opera 12+和Chrome。

数据类型

undefined

对未初始化的变量执行typeof操作会返回undefined值,而对于未声明的变量执行typeof操作同样会返回undefined值。

null

typeof null // -> object

undefined值派生自null值。

console.log(null == undefind)   // -> true

isFinite()

测试一个数值是不是无穷值。

Number.NEGATIVE_INFINITY:负无穷
Number.POSITION_INFINITY:正无穷

NaN

在ECMAScript中,任何数值除以0会返回NaN

isNaN()接受一个参数,确定这个参数是否"不是数值"。

数值转换

Number()

  • 如果是null,返回0
  • 如果是undefined,返回NaN

parseInt()
在ES5 中不支持解析八进制的能力。

parseInt('070');    // -> 70 not 56

通过第二个参数,指定转换基数(进制)默认十进制。

字符串

  • ECMAScript中的字符串是不可变的
  • toString()

在调用数值的toString方法,可以传递一个参数:输出数值的基数。没有toString方法的则返回该值的字面量

var num = 10;
console.log(num.toString(2));   // -> '1010'

object类型

Object类型的属性方法:

  • constructor
  • hasOwnProperty(propertyName)
  • isPrototypeOf(obj)
  • propertyIsEnumerable(propertyName)
  • toLocalString()
  • toString()
  • valueOf()

操作符

  • ++ or --

前置与后置的区别

var num1 = 2;
var num2 = 20;
var num3 = --num1 + num2;   // 21
var num4 = num1 + num2;     // 21

var num5 = 2;
var num6 = 20;
var num7 = num5-- + num6;   // 22
var num8 = num5 + num6;     // 21
  • 一元加操作符用于强制类型转换,隐式Number()效果

for-in 语句

for-in语句是一种精确的迭代语句,可以用来枚举对象的属性。

通过for-in循环输出的属性名的顺序是不可预测的。

如果要迭代的对象的变量值为nullundefinedfor-in语句会抛出错误。ES5更正了这一行为,不再抛出错误,只是不再执行循环体。

建议:在是使用for-in循环之前,先检查对象值是不是null或者undefined

变量、作用域和内存问题


基本类型和引用类型

复制变量值

  • 复制基本类型值,这两个变量相互独立,互不影响。
  • 复制引用类型(对象),值引用是一个指针,改变其中一个对象,会影响另一个对象。

传递参数

function setName(obj) {
    obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"

以上代码中创建一个对象,并将其保存在了变量person 中。然后,这个变量被传递到setName()函数中之后就被复制给了obj。在这个函数部,objperson 引用的是同一个对象。换句话说,即使这个变量是按值传递的,obj 也会按引用来访问同一个对象。于是,当在函数内部为obj 添加name属性后,函数外部的person 也将有所反映;因为person 指向的对象在堆内存中只有一个,而且是全局对象。有很多开发人员错误地认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的。为了证明对象是按值传递的,我们再看一看下面这个经过修改的例子:

function setName(obj) {
    obj.name = "Nicholas";
    obj = new Object();
    obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"

这个例子与前一个例子的唯一区别,就是在setName()函数中添加了两行代码:一行代码为obj重新定义了一个对象,另一行代码为该对象定义了一个带有不同值的name属性。在把person传递给setName()后,其name 属性被设置为"Nicholas"。然后,又将一个新对象赋给变量obj,同时将其name属性设置为"Greg"。如果person 是按引用传递的,那么person 就会自动被修改为指向其name属性值为"Greg"的新对象。但是,当接下来再访问person.name 时,显示的值仍然是"Nicholas"。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持未变。实际上,当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。

检测类型

虽然在检测基本数据类型时typeof 是非常得力的助手,但在检测引用类型的值时,这个操作符的用处不大。通常,我们并不是想知道某个值是对象,而是想知道它是什么类型的对象。为此,ECMAScript提供了instanceof 操作符。

延长作用域

  • try-catch语句中的catch
  • with语句

小结

  • 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
  • 从一个变量向另一个变量复制基本类型的值,会创建这个值的一个副本;
  • 引用类型的值是对象,保存在堆内存中;
  • 包含引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针;

引用类型


Array类型

检测数组

if (value instanceof Array) {

}

ECMAScript5新增了 Array.isArray()方法

if (Array.isArray(value)) {

}

sort方法

该方法有缺陷,sort()方法会调用每个数组项的toString()转型方法,然后比较字符串进行排序。

var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5

因此sort()方法接受一个比较函数作为参数。

function compare(value1, value2) {
    if (value1 < value2) {
        return -1;
    } else if (value1 > value2) {
        return 1;
    } else {
        return 0;
    }
}

var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0,1,5,10,15

splice方法

splice方法始终返回一个数组,该数组包含了从原始数组中删除的项。

var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); // 删除第一项
alert(colors); // green,blue
alert(removed); // red,返回的数组中只包含一项

removed = colors.splice(1, 0, "yellow", "orange"); // 从位置1 开始插入两项
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一个空数组

removed = colors.splice(1, 1, "red", "purple"); // 插入两项,删除一项
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,返回的数组中只包含一项

迭代方法

ECMAScript5为数组定义了5个迭代方法。

  • every(): 对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true。
  • filter(): 对数组中的每一项运行给定函数,返回该函数会返回true 的项组成的数组。
  • forEach(): 对数组中的每一项运行给定函数。这个方法没有返回值。
  • map(): 对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
  • some(): 对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true。

归并方法

ECMAScript 5 还新增了两个归并数组的方法。

  • reduce()
  • reduceRight()

reduce()reduceRight()的函数接收4 个参数:前一个值、当前值、项的索引和数组对象。

var values = [1, 2, 3, 4, 5];
var sum = values.reduce((prev, cur, index, array) => {
    return prev + cur;
});
console.log(sum);

RegExp类型

正则表达式中的元字符

( [ { \ ^ $ | ) ? * + . ] }

:匹配元字符必须转义

RegExp 构造函数

接受两个参数: 一个是要匹配的字符串模式,另一个是可选的标志字符串。

var pattern1 = /[bc]at/i;
// 等价于
var pattern2 = new RegExp('[bc]at', 'i');

:由于RegExp构造函数的模式是字符串,所以在某些情况下要对字符串进行双重转义,所有元字符都必须双重转义。例如\n在字符串中被转义为\\n,而在正则表达式字符串中就会变成\\\\n

RegExp实例方法

exex()方法

该方法是专门为捕获组而设计的。exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组;或者在没有匹配项的情况下返回null。返回的数组虽然是Array 的实例,但包含两个额外的属性:indexinput。其中,index 表示匹配项在字符串中的位置,而input 表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串(如果模式中没有捕获组,则该数组只包含一项)。

var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;

var matches = pattern.exec(text);
alert(matches.index); // 0
alert(matches.input); // "mom and dad and baby"
alert(matches[0]); // "mom and dad and baby"
alert(matches[1]); // " and dad and baby"
aler t(matches[2]); // " and baby"

对于exec()方法而言,即使在模式中设置了全局标志(g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息。而在设置全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项。

test()方法

接受一个字符串参数。在模式与该参数匹配的情况下返回true;否则,返回false

var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;

if (pattern.test(text)){
    alert("The pattern was matched.");
}

RegExp实例继承的toLocaleString()toString()方法都会返回正则表达式的字面量,与创建正则表达式的方式无关。

var pattern = new RegExp("\\[bc\\]at", "gi");
alert(pattern.toString()); // /\[bc\]at/gi
alert(pattern.toLocaleString()); // /\[bc\]at/gi

Function类型

函数声明与函数表达式

解析器会率先读取函数声明,并使其在执行任何代码之前可用;至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

// ok
alert(sum(10,10));
function sum(num1, num2){
    return num1 + num2;
}

// unexpected identifier(意外标识符)
alert(sum(10,10));
var sum = function(num1, num2){
    return num1 + num2;
};

:要访问函数的指针而不执行函数的话,必须去掉函数名后的那对圆括号。

函数内部属性

  • arguments
  • this

arguments具有一个callee属性,该属性是一个指针,指向拥有这个arguments对象的函数。

function factorial(num){
    if (num <=1) {
        return 1;
    } else {
        return num * factorial(num-1)
    }
}

等价于

function factorial(num){
    if (num <=1) {
        return 1;
    } else {
        return num * arguments.callee(num-1)
    }
}

达到一种解耦的效果。

ECMAScript 5也规范了一个函数对象属性:caller(看着很像callee),这个属性中保存着调用当前函数的函数的引用,如果实在全局作用域中调用当前函数,它的值为null

function outer(){
    inner();
}
function inner(){
    alert(inner.caller);
}
outer();

inner.caller指向outer()。为了实现更松散的耦合,也可以通过argument.callee.caller来访问相同的信息。

function outer() {
    inner();
}
function inner() {
    alert(arguments.callee.caller);
}
outer();

:当函数在严格模式下运行时,访问arguments.callee 会导致错误。ECMAScript 5 还定义了arguments.caller属性,但在严格模式下访问它也会导致错误,而在非严格模式下这个属性始终是undefined。定义这个属性是为了分清arguments.caller 和函数的caller 属性。以上变化都是为了加强这门语言的安全性,这样第三方代码就不能在相同的环境里窥视其他代码了。
严格模式还有一个限制:不能为函数的caller 属性赋值,否则会导致错误。

函数属性和方法

每个函数都包含两个属性:

  • length: 表示函数希望接收的命名参数的个数
  • prototype: 保存实例方法

每个函数都包含两个非继承而来的方法:

  • apply()
  • call()
    这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this 对象的值。首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array 的实例,也可以是arguments对象。
    call()方法与apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于call()方法而言,第一个参数是this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用call()方法时,传递给函数的参数必须逐个列举出来。

:在严格模式下,未指定环境对象而调用函数,则this 值不会转型为window。除非明确把函数添加到某个对象或者调用apply()call(),否则this 值将是undefined

在非严格模式下,callapply的第一个参数传递为nullundefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window

ECMAScript 5定义了一个方法bind(),这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

基本包装类型

使用new调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。

var value = '25';
var number = Number(value); // 转型函数
console.log(typeof number); // 'number'

var obj = new Number(value); // 构造函数
console.log(typeof obj);    // 'object'

Number类型

Number类型的toString()方法很特别,可以传递一个表示基数的参数。

var num = 10;
alert(num.toString()); //"10"
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
alert(num.toString(10)); //"10"
alert(num.toString(16)); //"a"

String类型

字符方法
  • charAt()
  • charCodeAt()
var stringValue = "hello world";

alert(stringValue.charAt(1)); //"e"
alert(stringValue.charCodeAt(1)); //输出字符编码"101"
字符串操作方法
  • concat()
  • slice()
  • substr()
  • substring()

这些方法对原字符均没有任何影响。

var stringValue = "hello ";
var result = stringValue.concat("world", "!");
alert(result); //"hello world!"

var stringValue = "hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3, 7)); //"lo w"
alert(stringValue.substring(3,7)); //"lo w"
alert(stringValue.substr(3, 7)); //"lo worl"

// 参数是负值的情况下,它们的行为就不尽相同了。
// 其中,slice()方法会将传入的负值与字符串的长度相加,
// substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为0。
// 最后,substring()方法会把所有负值参数都转换为0。
alert(stringValue.slice(-3)); //"rld"
alert(stringValue.substring(-3)); //"hello world"
alert(stringValue.substr(-3)); //"rld"
alert(stringValue.slice(3, -4)); //"lo w"
alert(stringValue.substring(3, -4)); //"hel"
alert(stringValue.substr(3, -4)); //""(空字符串)
字符串位置方法
  • indexOf()
  • lastIndexOf()

两个方法的第二个参数,表示从字符串中哪个位置开始搜索。

trim()方法

ECMAScript 5方法

字符串转换大小写方法
  • toLowerCase()
  • toLocaleLowerCase()
  • toUpperCase()
  • toLocaleUpperCase()
字符串的模式匹配方法
  • match()
  • search()
  • replace()
  • split()

match()方法,在字符串上调用这个方法,本质上和调用RegExpexec()方法相同。match()方法只接受一个参数,要么是一个正则表达式,要么是一个RegExp对象。

var text = 'cat, bat, sat, fat';
var pattern = /.at/;

// 等价于 pattern.exec(text)
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0

search()方法的参数与match()方法相同,该方法返回字符串中第一个匹配项的索引,没有匹配项返回-1;个人认为serch()就是正则版的indexOf()

var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
aler t(pos); //1

ECMAScript提供了replace()方法,该方法接受两个参数,第一个参数可以是RegExp对象或者是一个字符串,第二个参数可以是一个字符串或者一个函数。

var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cond, bat, sat, fat"

result = text.replace(/at/g, "ond");
aler t(result); //"cond, bond, sond, fond"

| 字符序列 | 替换文本 |
| : - : | : -- : |
| $$ | $ |
| $& | 匹配整个模式的子字符串。RegExp.lastMatch |
| $' | 匹配子字符串之前的字符串。RegExp.leftContext |
| $` | 匹配的子字符串之后的字符串。 RegExp.rightContext |
| $n | 匹配第n个捕获组的子字符串 n: 0~9 |
| $nn | 匹配第nn个捕获组的子字符串 nn: 01~99 |

var text = "cat, bat, sat, fat";
result = text.replace(/(.at)/g, "word ($1)");
alert(result); //word (cat), word (bat), word (sat), word (fat)

split()方法可以基于指定的分隔符(字符串 or RegExp对象)将一个字符串分割成多个子字符串,并将结构放在一个数组中。可以接受可选的第二个参数,用于指定数组的大小。

var colorText = "red,blue,green,yellow";
var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]
localeCompare()方法

比较两个字符串,并返回下列值中的 一个:

  • 如果字符串在字母表中应该排在字符串参数之前,则返回一个负数
  • 如果字符串等于字符串参数,则返回0;
  • 如果字符串在字母表中应该排在字符串参数之后,则返回一个正数
var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("yellow")); //0
alert(stringValue.localeCompare("zoo")); //-1
fromCharCode()方法

这个方法的任务是接收一个或多个字符编码,然后将它们转换成一个字符串。相当于charCodeAt()反操作。

alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"

Math 对象

  • min()
  • max()
  • ceil()
  • floor()
  • round()
  • random()

面向对象的程序设计

理解对象

属性类型

数据类型
  • [[Configurable]]: 表示能否通过delete删除属性从而重新定义属性,能够修改属性的特性,或者能否把属性修改为访问器属性
  • [[Enumerable]]: 表示能否通过for-in循环返回属性
  • [[Writable]]: 表示能否修改属性的值
  • [[Value]]: 包含这个属性的数据值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置。默认值undefined

要修改属性默认的特性,必须使用ECMAScript 5Object.defineProperty()方法。这个方法接受三个参数:属性所在对象,属性名和一个描述符对象。其中描述符对象的属性值必须是:configurableenumerablewritablevalue。设置其中一个或多个。

var person = {};
Object.defineProperty(person, 'name', {
    writable: false,
    value: 'Yeaseon'
});

Object.defineProperty()方法不能对configurable: false的对象进行修改。

访问器属性
  • [[Configurable]]: 表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为数据属性。
  • [[Enumerable]]: 表示能否通过for-in循环返回属性。
  • [[Get]]: 在读取属性时调用的函数,默认undefined
  • [[Set]]: 在写入属性时调用的函数,默认undefined
var book = {
    _year: 2004,
    edition: 1
};
Object.defineProperty(book, "year", {
    get: function(){
        return this._year;
    },
    set: function(newValue){
        if (newValue > 2004) {
            this._year = newValue;
            this.edition += newValue - 2004;
        }
    }
});
book.year = 2005;
alert(book.edition); //2

读取属性的特性

ECMAScript 5Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。该方法接收两个参数:属性所在的对象和要读取器描述符的属性名称,返回值是对象。

创建对象

工厂模式

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");

构造函数模式

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 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"

Person.prototype.constructor会指向Personperson1并没有直接连接到构造函数Person

JS红宝书·读书笔记 -- 上篇_第2张图片
  • 可以通过isPrototypeOf()方法来确定对象之间是否存在原型关系。从本质上讲,[[Prototype]]指向调用isPrototypeOf()方法的对象Person.prototype,则会返回true
alert(Person.prototype.isPrototypeOf(person1)); //true

ECMAScript 5增加了Object.getPrototypeOf()方法,该方法返回[[Prototype]]的值。

alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"

: 虽然可以通过对象实例person1访问保存在原型中的值,但却不能重写原型中的值。

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();
var person2 = new Person();

person1.name = "Greg"; //实质是在实例上增加一个name属性
alert(person1.name); //"Greg"——来自实例
alert(person2.name); //"Nicholas"——来自原型

可以通过delete删除实例属性,从而继续访问原型中的属性。

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.name = "Greg";
alert(person1.name); //"Greg"——来自实例

delete person1.name;
alert(person1.name); //"Nicholas"——来自原型
  • hasOwnProperty()方法可以检测一个属性是不是存在于实例,是则返回true
JS红宝书·读书笔记 -- 上篇_第3张图片
  • in操作符
    (prop in obj)通过in操作符可以判定对象是否有该属性,不论是本身含有还是原型含有,都返回true
    可以通过in配合hasOwnProperty()确定该属性是存在于对象中还是原型中:
function detectProperty(obj, name) {
    if (name in obj) {
        obj.hasOwnProperty(name) ? '在对象中' : '在原型中';
    } else {
        console.log('不含有该属性');
    }
}
  • ECMAScript 5Object.keys()方法可以取得对象上所有可枚举的实例属性。
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    alert(this.name);
};
var keys = Object.keys(Person.prototype);
alert(keys); //"name,age,job,sayName"

var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var p1keys = Object.keys(p1);
alert(p1keys); //"name,age"
  • Object.getOwnPropertyNames会得到所有实例属性,不论是否可枚举。
var keys = Object.getOwnPropertyNames(Person.prototype);
alert(keys); //"constructor,name,age,job,sayName"

简化Person.prototype写法:

function Person(){
}
Person.prototype = {
    name : "Nicholas",
    age : 29,
    job: "Software Engineer",
    sayName : function () {
        alert(this.name);
    }
};

这样写有一个缺陷,constructor属性则会等于Object,我们需要手动设置constructor

function Person(){
}
Person.prototype = {
    constructor : Person,
    name : "Nicholas",
    age : 29,
    job: "Software Engineer",
    sayName : function () {
        alert(this.name);
    }
};

但这同时也会导致constructor[[Enumerable]]特性变成了true,默认情况下是false。再修改下写法:

function Person(){
}
Person.prototype = {
    name : "Nicholas",
    age : 29,
    job : "Software Engineer",
    sayName : function () {
        alert(this.name);
    }
};

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
JS红宝书·读书笔记 -- 上篇_第4张图片

结合使用构造函数和原型模式

用构造函数模式定义实例属性,用原型模式定义方法和共享属性。

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 SuperType () {
    this.property = true;
}

SuperType.prototype.getSuperValue = function () {
    return this.property;
};

function SubType () {
    this.subproperty = false;
}

SubType.prototype = new SuperType();

SubType.prototype.getSubValue = function () {
    return this.subproperty;
};

var instance = new SubType();
console.log(instance.getSuperValue());  // true
JS红宝书·读书笔记 -- 上篇_第5张图片
instanceof操作符

用来确定原型和实例之间的关系。

alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true

第二种方式就是isPrototypeOf()方法,只要原型链中出现过的原型,都可以说是该原型链所派生的实例的原型。

alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true

函数表达式

由于有声明提升的存在,定义函数不要放在条件表达式中

if (condition) {
    function sayHi () {
        console.log('Hi');
    }
} else {
    function sayHi () {
        console.log('Yo');
    }
}

ECMAScript中属于无效语法,在不同浏览器中修正的做法并不一致。推荐的写法,如下:

var sayHi;

if (condition) {
    sayHi = function () {
        console.log('Hi');
    }
} else {
    sayHi = function () {
        console.log('Yo');
    }
}

这种函数表达式不存在声明提升,所以OK。

递归

函数作用域链

当某个函数被调用时,会创建一个执行环境及相应的作用域链。然后,使用arguments和其他命名参数的值来初始化函数的活动对象。在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位...,直到作用域终点的全局执行环境。

闭包

function createFunctions () {
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
function createFunction () {
    var result = new Array();
    for (var i = 0; i < 10; i++) {
        result[i] = function (num) {
            return function () {
                return num;
            };
        }(i);
    }
    return result;
}

:在闭包中使用this对象可能会导致一些问题。匿名函数的执行环境具有全局性,因此其this对象通常指向window

var name = 'The window';

var obj = {
    name: 'my object',
    getNameFunc: function () {
        return function () {
            return this.nam;
        }
    }
}

console.log(obj.getNameFunc()());  // The Window (非严格模式)

模仿块级作用域

块级作用域

(function () {
    // 这里是块级作用域
})();

BOM


window 对象

全局作用域

抛开全局变量会成为window对象的属性不谈,定义全局变量与在window对象上直接定义属性还是有一点差别:全局变量不能通过delete操作符删除,而直接定义在window对象上的定义的属性可以

窗口位置

获得窗口左边和上边的位置。

var leftPos = (typeof window.screenLeft == 'number') ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == 'number') ? window.screenTop : window.screenY;

Firefox支持screenXscreenY,其他浏览器均支持screenLeftscreenTop

但是还是需要注意一个问题:在IE Opera中,screenLeft screenTop 保存的的是可见区域的距离,也就是我们浏览器中不包含工具栏的区域与屏幕的距离;在ChromeFirefoxSafariscreenYscreenTop返回的是整个浏览器窗口相对于屏幕坐标的值。

窗口大小

IE9+、Firefox、Safari、Opera和Chrome均提供了4个属性innerWidthinnerHeightouterWidthouterHeight

  • IE9+、Safari和Firefox中,outerWidthouterHeight返回浏览器窗口本身的尺寸,而innerWidthinnerHeight则表示该容器中页面视图区的大小(减去边框宽度)
  • Chrome中,inner*outer*返回相同的值,即视口大小而非浏览器窗口的大小。
  • 在IE、Firefox、Safari、Opera和Chrome中,都能通过document.documentElement.clientWidthdocument.documentElement.clientHeight中保存了页面视口信息。

获取页面视口大小

var pageWidth = window.innerWidth,
    pageHeight = window.innerHeight;

if (typeof pageWidth != 'number') {
    if (document.compatMode == 'CSS1Compat') { // 浏览器标准模式
        pageWidth = document.documentElement.clientWidth;
        pageHeight = document.documentElement.clientHeight;
    } else {  // IE6 混杂模式
        pageWidth = document.body.clientWidth;
        pageHeight = document.doby.clientHeight;
    }
}
  • resizeTo()接受浏览器窗口的新宽度和新高度
  • resizeBy()接受新窗口与原窗口的宽度和高度差。

这两个方法可能被浏览器禁用。

导航

如果是浏览器内置的屏蔽程序组织的弹出窗口,那么window.open()很可能会返回null

var newWindow = window.open('https://www.google.com.hk', '_blank');
if (newWindow == null) {
    console.log('The popup was blocked!');
}

如果是浏览器扩展或其他程序组织的弹出窗口,那么window.open()通常会抛出一个错误。

var blocked = false;

try {
    var newWindow = window.open('https://www.google.com.hk', '_blank');
    if (newWindow == null) {
        blocked = true;
    }
} catch (ex) {
    blocked = true;
}

if (blocked) {
    console.log('The popup was blocked');
}

location 对象

location对象的属性

  • hash
  • host
  • hostname:与host不同的是,不带端口号
  • href
  • pathname: 返回URL中的目录和(或)文件名
  • port
  • protocol
  • search:返回URL的查询字符串,这个字符串?开头

navigator 对象

location对象的属性

  • appCodeName: 浏览器的名称,通常都是Mozilla
  • appMinorVersion:此版本信息
  • appName: 完整的浏览器名称
  • appVersion:浏览器的版本
  • buildID:浏览器编译版本
  • cookieEnabled:表示cookie是否可用
  • cpuClass:客户端计算机中使用的CPU类型
  • javaEnabled():表示当前浏览器中是否启用了java
  • language: 浏览器的主语言
  • mimeTypes:浏览器中注册的MIME类型数组
  • onLine:表示浏览器是都连接到因特网
  • oscpu:客户端计算机的操作系统或使用的CPU
  • platform:浏览器所在的系统平台
  • plugins:浏览器中安装的插件信息的数组
  • preference():设置用户的首选项
  • systemLanguage:操作系统的语言
  • userAgent:浏览器的用户代理字符串

DOM


节点层次

Node类型

每个节点都有一个nodeType属性,用于表明节点的类型。

  • Node.ELEMENT_NODE(1)
  • Node.ATTRIBUTE_NODE(2)
  • Node.TEXT_NODE(3)
  • Node.CDATA_SECTION_NODE(4)
  • Node.ENTITY_REFERENCE_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)

为了确保跨浏览器兼容,将nodeType属性与数字值进行比较:

if (someNode.nodeType == 1) {
    console.log('Node is an element');
}
  • nodeName属性
if (someNode.nodeType == 1) {
    var value = someNode.nodeName;  // nodeName的值是元素的标签名
}
节点关系
  • childNodes属性

每个节点都有一个childNodes属性,其中保存着一个NodeList对象,该对象是一种类数组对象。

  • parentNode属性

每个节点都有一个parentNode属性,该属性指向文档树中的父节点。包含在childNodes列表中的每个节点相互都是兄弟节点。使用previousSiblingnextSibling属性,可以访问其他兄弟节点。

:列表中第一个节点的previousSibling属性值为null,同理列表中最后一个节点的nextSibling属性也是null。父节点的firstChildlastChild属性分别指向其childNodes列表中的第一个和最后一个节点。如果不存在则为null

hasChildNodes()方法在节点包含一个或多个子节点的情况下返回true,比查询childNodes.length更简便。

最后一个属性ownerDocument,该属性指向表示整个文档的文档节点(root),直接返回根节点不需要一层层向上回溯。

操作节点
  • appendChild()

用于向childNodes列表的末尾添加一个节点。

var returnedNode = someNode.appendChild(newNode);
alert(returnedNode == newNode); //true
alert(someNode.lastChild == newNode); //true

任何DOM节点不可能同时出现在多个位置。

//someNode 有多个子节点
var returnedNode = someNode.appendChild(someNode.firstChild);
alert(returnedNode == someNode.firstChild); //false
alert(returnedNode == someNode.lastChild); //true
  • insertBefore()

把节点放在指定位置,该方法接受两个参数:要插入的节点和作为参考的节点。插入节点后,被插入的节点会变成参照节点的前一个兄弟节点。参照节点是null的话,insertBeforeappendChild执行相同的操作,都插入列表末尾。

//插入后成为最后一个子节点
returnedNode = someNode.insertBefore(newNode, null);
alert(newNode == someNode.lastChild); //true

//插入后成为第一个子节点
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); //true
alert(newNode == someNode.firstChild); //true

//插入到最后一个子节点前面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length-2]); //true
  • replaceChild()

替换节点,接受两个参数:要插入的节点和要替换的节点。

//替换第一个子节点
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);

//替换最后一个子节点
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
  • removeChild()

移除节点,接受一个参数:要被移除的节点。

//移除第一个子节点
var formerFirstChild = someNode.removeChild(someNode.firstChild);

//移除最后一个子节点
var formerLastChild = someNode.removeChild(someNode.lastChild);
  • cloneNode()

复制节点,接受一个布尔值,表示是否深复制。复制后返回的节点没有父节点,可以通过插入等操作手动指定。

var deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); //3(IE < 9)或7(其他浏览器)

var shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); //0

cloneNode方法不会复制DOM节点的js属性。IE存在一个bug,它会复制事件处理程序。

  • normalize()

稍后讨论

以上方法的返回值,都是被操作的节点。

Document类型

Document节点具有下列特征:

  • nodeType的值为9
  • nodeName的值为#document
  • nodeValue的值为null
  • parentNode的值为null
  • ownerDocument的值为null
  • 其子节点可能是一个DocumentType(最多一个)、Element(最多一个)、ProcessingInstructionComment
// 通过`documentElement`属性访问元素
var html = document.documentElement;
// 访问  元素
var body = document.body;
// 
var doctype = document.doctype;
// 
var title = document.title;
// 完整 url
var url = document.URL;
// domain 域名
var domain = document.domain;
// 取得来源页面的URL(也就是导航到这页的页面)
var referrer = document.referrer;
</code></pre> 
 <p>查找元素的方法:</p> 
 <ul> 
  <li><code>document.getElementById()</code></li> 
  <li><code>document.getElementsByTagName()</code></li> 
  <li><code>document.getElementsByName()</code></li> 
 </ul> 
 <p>文档写入:</p> 
 <ul> 
  <li><code>document.write()</code></li> 
  <li> <code>document.writeln()</code>在字符串尾加换行符(\n)</li> 
 </ul> 
 <pre><code><script type="text/javascript">
    document.write("<script type=\"text/javascript\" src=\"file.js\">" + "<\/script>");
</script>
</code></pre> 
 <h4>Element类型</h4> 
 <p><code>Element</code>类型提供了对元素标签名、子节点及特性的访问。</p> 
 <ul> 
  <li> <code>nodeType</code>的值为1</li> 
  <li> <code>nodeName</code>的值为元素的标签名</li> 
  <li> <code>nodeValue</code>的值为<code>null</code> </li> 
  <li> <code>parentNode</code>可能是<code>Document</code>或<code>Element</code> </li> 
  <li>其子节点可能是<code>Element</code>、<code>Text</code>、<code>Comment</code>、<code>ProcessingInstruction</code>、<code>CDATASection</code>或<code>EntityReference</code> </li> 
 </ul> 
 <p>访问元素的标签名,可以使用<code>nodeName</code>属性,也可以使用<code>tagName</code>属性,后者更直观。</p> 
 <pre><code><div id="myDiv"></div>

var div = document.getElementById("myDiv");
alert(div.tagName); //"DIV"
alert(div.tagName == div.nodeName); //true
</code></pre> 
 <p>操作特性的方法:</p> 
 <ul> 
  <li><code>getAttribute()</code></li> 
  <li><code>setAttribute()</code></li> 
  <li><code>removeAttribute()</code></li> 
 </ul> 
 <p><code>attributes</code>属性</p> 
 <p><code>Element</code>类型是使用<code>attributes</code>属性的唯一一个DOM节点属性。<code>attributes</code>属性包含一个<code>NamedNodeMap</code>。元素的每一个特性都由一个<code>Attr</code>节点表示,每个节点都保存在<code>NamedNodeMap</code>对象中。</p> 
 <p><code>NamedNodeMap</code>对象的方法:</p> 
 <ul> 
  <li> <code>getNamedItem(name)</code>:返回<code>nodeName</code>属性等于<code>name</code>的节点</li> 
  <li> <code>removeNamedItem(name)</code>:从列表中移除<code>nodeName</code>属性等于<code>name</code>的节点</li> 
  <li> <code>setNamedItem(node)</code>:向列表中添加节点,以节点的<code>nodeName</code>属性为索引</li> 
  <li> <code>item(pos)</code>:返回位于数字<code>pos</code>位置处的节点</li> 
 </ul> 
 <p><code>attributes</code>属性中包含一系列节点,每个节点的<code>nodeName</code>就是特性的名称,而节点<code>nodeValue</code>就是特性的值。</p> 
 <pre><code>var id = element.attributes.getNamedItem('id').nodeValue;
// 简写
var id = element.attributes['id'].nodeValue;
</code></pre> 
 <p>创建元素<br> <code>document.createElement()</code>方法可以创建新元素,这个方法接受一个参数(标签名)</p> 
 <pre><code>var div = document.createElement('div');
</code></pre> 
 <h4>Text类型</h4> 
 <p>文本节点由<code>Text</code>类型表示,包含的是可以照字面解释的纯文本内容。纯文本中可以包含转义后的HTML字符,但不能包含HTML代码。</p> 
 <ul> 
  <li> <code>nodeType</code>的值为3</li> 
  <li> <code>nodeName</code>的值为<code>#text</code> </li> 
  <li> <code>nodeValue</code>的值为节点所包含的文本</li> 
  <li> <code>parentNode</code>是一个<code>Element</code> </li> 
 </ul> 
 <p>操作节点中的文本:</p> 
 <ul> 
  <li> <code>appendData(text)</code>:将<code>text</code>添加到节点的末尾</li> 
  <li> <code>deleteData(offset, count)</code>:从<code>offset</code>指定的位置开始删除<code>count</code>个字符</li> 
  <li> <code>insertData(offset, text)</code>:在<code>offset</code>指定的位置插入<code>text</code> </li> 
  <li> <code>replaceData(offset, count, text)</code>:用<code>text</code>替换从<code>offset</code>指定的位置开始到<code>offset+count</code>为止的文本</li> 
  <li> <code>splitText(offset)</code>:从<code>offset</code>指定的位置将当前文本分成两个文本节点</li> 
  <li> <code>substringData(offset, count)</code>:提取从<code>offset</code>指定的位置开始到<code>offset+count</code>为止处的字符串。</li> 
 </ul> 
 <p>在向DOM文档中插入文本之前,应该先对其进行<code>HTML</code>编码</p> 
 <p>创建文本节点</p> 
 <ul> 
  <li><code>document.createTextNode()</code></li> 
 </ul> 
 <pre><code>var textNode = document.createTextNode("<strong>Hello</strong> world!");
</code></pre> 
 <h3>DOM 操作技术</h3> 
 <p>使用函数实现加载外部<code>JS</code>文件</p> 
 <pre><code>function loadScript(url) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    document.body.appendChild(script);
}
loadScirpt('xx.js');
</code></pre> 
 <p>IE将<code><script></code>视为一个特殊的元素,不允许DOM访问其子节点。不过可以使用<code><script></code>元素的<code>text</code>属性指定<code>JS</code>代码。</p> 
 <h4>操作表格</h4> 
 <pre><code>// create table
var table = document.createElement('table');
table.border = 1;
table.width = '100%';

// create tbody
var tbody = document.createElement('tbody');
table.appendChild(tbody);

// create row1
var row1 = document.createElement('tr');
tbody.appendChild(row1);

var cell1_1 = document.createElement('td');
cell1_1.appendChild(document.createTextNode('Cell 1,1'));
row1.appendChild(cell1_1);

var cell2_1 = document.createElement('td');
cell2_1.appendChild(document.createTextNode('Cell 2,1'));
row1.appendChild(cell2_1);

// create row2
var row2 = document.createElement('tr');
tbody.appendChild(row2);

var cell1_2 = document.createElement('td');
cell1_2.appendChild(document.createTextNode('Cell 1,2'));
row1.appendChild(cell1_2);

var cell2_2 = document.createElement('td');
cell2_2.appendChild(document.createTextNode('Cell 2,2'));
row1.appendChild(cell2_2);

document.body.appendChild(table);
</code></pre> 
 <h2>DOM 扩展</h2> 
 <hr> 
 <h3>选择符 API</h3> 
 <ul> 
  <li> <code>querySelector()</code>方法</li> 
 </ul> 
 <p><code>querySelector()</code>方法接受一个<strong>CSS</strong>选择符,返回与该模式匹配的<strong>第一个元素</strong>,若没有,返回<code>null</code>。</p> 
 <p>可以通过<code>Document</code>类型调用,也可以通过<code>Element</code>类型调用,后者只会在该元素后代元素的范围内查找匹配的元素。</p> 
 <ul> 
  <li> <code>querySelectorAll()</code>方法</li> 
 </ul> 
 <p><code>querySelectorAll()</code>方法返回的是所有匹配的元素,是一个<code>NodeList</code>实例。</p> 
 <ul> 
  <li> <code>matchesSelector()</code>方法</li> 
 </ul> 
 <p>为<code>Element</code>类型新增的一个方法,接受一个参数<code>CSS</code>选择符,如果调用元素与该选择符匹配,返回<code>true</code>,否则返回<code>false</code>。</p> 
 <h3>元素遍历</h3> 
 <ul> 
  <li> <code>childElementCount</code>:返回子元素(不包含文本节点和注释)的个数</li> 
  <li> <code>firstElementChild</code>:指向第一个子元素</li> 
  <li> <code>lastElementChild</code>:指向最后一个子元素</li> 
  <li> <code>previousElementSibling</code>:指向前一个兄弟元素</li> 
  <li> <code>nextElementSibling</code>:指向后一个兄弟元素</li> 
 </ul> 
 <p>不同于前面的返回<strong>节点</strong>的方法。</p> 
 <pre><code>// 节点版本
var i,
    len,
    child = element.firstChild;
while(child != element.lastChild){
    if (child.nodeType == 1){ //检查是不是元素
        processChild(child);
    }
    child = child.nextSibling;
}
// 元素版本
var i,
    len,
    child = element.firstElementChild;
while(child != element.lastElementChild){
    processChild(child); //已知其是元素
    child = child.nextElementSibling;
}
</code></pre> 
 <h3>HTML5</h3> 
 <ul> 
  <li> <code>getElementsByClassName()</code>方法</li> 
  <li> <code>classList</code>属性,这个属性是新集合类型<code>DOMTokenList</code>的实例。 
   <ul> 
    <li><code>add(value)</code></li> 
    <li><code>contains(value)</code></li> 
    <li><code>remove(value)</code></li> 
    <li><code>toggle(value)</code></li> 
   </ul> </li> 
 </ul> 
 <pre><code>div.classList.remove("user");
</code></pre> 
 <h4>焦点管理</h4> 
 <p><code>document.activeElement</code>属性,始终会引用DOM中前端获得了焦点的元素。</p> 
 <pre><code>var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
</code></pre> 
 <p><code>document.hasFocus()</code>方法,可以确定文档是否获得了焦点。</p> 
 <pre><code>var button = document.getElementById("myButton");
button.focus();
alert(document.hasFocus()); //true
</code></pre> 
 <h4> <code>HTMLDocument</code>的变化</h4> 
 <pre><code>+ `readyState`属性有两个值,`loading`和`complete`
</code></pre> 
 <pre><code>if (document.readyState == 'complete') {
    // 加载完成
}
</code></pre> 
 <h4> <code>document.charset</code>字符集属性</h4> 
 <h4> <code>data-</code>自定义数据属性</h4> 
 <pre><code><div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>

var div = document.getElementById("myDiv");

//取得自定义属性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;

//设置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
</code></pre> 
 <h4> <code>innerHTML</code>属性</h4> 
 <p>在读模式下,<code>innerHTML</code> 属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应<br> 的HTML 标记。在写模式下,<code>innerHTML</code> 会根据指定的值创建新的DOM树,然后用这个DOM树完全<br> 替换调用元素原先的所有子节点</p> 
 <h4> <code>outerHTML</code>属性</h4> 
 <p>在读模式下,<code>outerHTML</code> 返回调用它的元素及所有子节点的HTML 标签。在写模式下,<code>outerHTML</code><br> 会根据指定的HTML 字符串创建新的DOM 子树,然后用这个DOM子树完全替换调用元素。</p> 
 <h4> <code>insertAdjacentHTML()</code>方法</h4> 
 <p>插入元素的新增方法,接受两个参数,插入的位置和要插入的HTML文本,第一个参数的值:</p> 
 <ul> 
  <li><code>'beforebegin'</code></li> 
  <li><code>'afterbegin'</code></li> 
  <li><code>'beforeend'</code></li> 
  <li><code>'afterend'</code></li> 
 </ul> 
 <pre><code>//作为前一个同辈元素插入
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");

//作为第一个子元素插入
element.insertAdjacentHTML("afterbegin", "<p>Hello world!</p>");

//作为最后一个子元素插入
element.insertAdjacentHTML("beforeend", "<p>Hello world!</p>");

//作为后一个同辈元素插入
element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
</code></pre> 
 <h4> <code>scrollIntoView()</code>方法</h4> 
 <p><code>scrollIntoView</code>方法可以在所有HTML元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果这个方法传入<code>true</code>作为参数,或者不传参数,那么窗口滚动之后就会让调用元素的顶部与视口顶部 尽可能平齐,如果传入<code>false</code>,调用元素会尽可能全部出现在视口中,不过顶部不一定平齐。</p> 
 <pre><code>// 让元素可见
document.form[0].scrollIntoView();
</code></pre> 
 <h3>专有扩展</h3> 
 <h4>插入文本</h4> 
 <ul> 
  <li> <code>innerText</code>属性</li> 
  <li> <code>outerText</code>属性</li> 
 </ul> 
 <h4>滚动</h4> 
 <ul> 
  <li> <code>scrollIntoViewIfNeeded(alignCenter)</code>:只有在当前元素不可见的情况下,才滚动浏览器或窗口或容器元素最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。</li> 
  <li> <code>scrollByLines(lineCount)</code>:将元素的内容滚动指定的行高,<code>lineCount</code>值可以是正值,也可以是负值。</li> 
  <li> <code>scrollByPages(pageCount)</code>:将元素的内容滚动指定的页面高度,具体高度由元素的高度决定。</li> 
 </ul> 
 <p><code>scrollIntoView()</code>和<code>scrollIntoViewIfNeeded()</code>的作用对象是元素的容器,而<code>scrollByLines()</code>和<code>scrollByPages()</code>影响的则是元素自身。</p> 
 <pre><code>//在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();

//将页面主体往回滚动1 页
document.body.scrollByPages(-1);
</code></pre> 
 <h2>DOM2 和 DOM3</h2> 
 <hr> 
 <h3>样式</h3> 
 <h3>元素大小</h3> 
 <h4>偏移量</h4> 
 <ul> 
  <li> <code>offsetHeight</code>:元素在垂直方向上占用的空间大小。包括元素的高度,(可见的)水平滚动条的高度,上边框高度和下边框高度</li> 
  <li> <code>offsetWidth</code>:元素在水平方向上占用的空间大小。包括元素的宽度,(可见的)垂直滚动条的宽度,左边框宽度和右边框宽度</li> 
  <li> <code>offsetLeft</code>:元素的左外边框至包含元素的左内边框之间的像素距离。</li> 
  <li> <code>offsetTop</code>:元素的上外边框至包含元素的上内边框之间的像素距离。</li> 
 </ul> 
 <div class="image-package"> 
  <div class="image-container" style="max-width: 700px; max-height: 387px;"> 
   <div class="image-view"> 
    <a href="http://img.e-com-net.com/image/info10/6c7c4f00f7d143c19930af69c5c2ce64.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info10/6c7c4f00f7d143c19930af69c5c2ce64.jpg" width="650" height="355" alt="JS红宝书·读书笔记 -- 上篇_第6张图片" style="border:1px solid black;"></a> 
   </div> 
  </div> 
  <div class="image-caption"></div> 
 </div> 
 <p>其中,<code>offsetLeft</code>和<code>offsetTop</code>属性与包含元素有关,包含元素的引用保存在<code>offsetParent</code>属性中。<code>offsetParent</code>属性不一定与<code>parentNode</code>的值相等。</p> 
 <pre><code>// 元素上偏移
function getElementLeft (ele) {
    var actualLeft = ele.offsetLeft;
    var current = ele.offsetParent;

    while (current !== null) {
        actualLeft += current.offsetLeft;
        current = current.offsetParent;
    }
    return actualLeft;
}
// 元素左偏移同理
</code></pre> 
 <p>一般来说,页面中所有的元素都被包含在几个<code><div></code>元素中,而这些<code><div></code>元素的<code>offsetParent</code>又是<code><body></code>元素,所以<code>getElementLeft()</code>与<code>getElementTop()</code>会返回与<code>offsetLeft</code>和<code>offsetTop</code>相同的值。</p> 
 <h4>客户区大小</h4> 
 <ul> 
  <li> <code>clientWidth</code>:元素内容区宽度加上左右内边距宽度</li> 
  <li> <code>clientHeight</code>: 元素内容区高度加上上下内边距高度</li> 
 </ul> 
 <div class="image-package"> 
  <div class="image-container" style="max-width: 647px; max-height: 391px;"> 
   <div class="image-view"> 
    <a href="http://img.e-com-net.com/image/info10/740185b44ee64e8793cae11a07c2faca.png" target="_blank"><img src="http://img.e-com-net.com/image/info10/740185b44ee64e8793cae11a07c2faca.png" width="647" height="391" alt="JS红宝书·读书笔记 -- 上篇_第7张图片" style="border:1px solid black;"></a> 
   </div> 
  </div> 
  <div class="image-caption"></div> 
 </div> 
 <pre><code>function getViewport(){
    if (document.compatMode == "BackCompat"){  // IE7之前
            return {
                width: document.body.clientWidth,
                height: document.body.clientHeight
            };
        } else {
            return {
                width: document.documentElement.clientWidth,
                height: document.documentElement.clientHeight
            };
        }
}
</code></pre> 
 <h4>滚动大小</h4> 
 <p><strong>滚动大小</strong>,指的是包含滚动内容的元素的大小。有些元素(<code><html></code>),即使没有执行任何代码也能自动添加滚动条;但另外一些元素,则需要通过<strong>CSS</strong>的<code>overflow</code>属性设置才能滚动。</p> 
 <ul> 
  <li> <code>scrollHeight</code>:在没有滚动条的情况下,元素内容的总高度</li> 
  <li> <code>scrollWidth</code>:在没有滚动条的情况下,元素内容的总宽度</li> 
  <li> <code>scrollLeft</code>:被隐藏在内容区域左侧的像素数,通过设置这个属性可以改变元素的滚动位置</li> 
  <li> <code>scrollTop</code>:被隐藏在内容区域上方的像素数,通过设置这个属性可以改变元素的滚动位置</li> 
 </ul> 
 <div class="image-package"> 
  <div class="image-container" style="max-width: 700px; max-height: 440px;"> 
   <div class="image-view"> 
    <a href="http://img.e-com-net.com/image/info10/051ea3b939944d649bb62c53f43e4adb.jpg" target="_blank"><img src="http://img.e-com-net.com/image/info10/051ea3b939944d649bb62c53f43e4adb.jpg" width="650" height="388" alt="JS红宝书·读书笔记 -- 上篇_第8张图片" style="border:1px solid black;"></a> 
   </div> 
  </div> 
  <div class="image-caption"></div> 
 </div> 
 <p><code>scrollWidth</code>和<code>scrollHeight</code>主要用于确定元素内容的实际大小。</p> 
 <p><code>scrollWidth</code> 和<code>scrollHeight</code> 与<code>clientWidth</code> 和<code>clientHeight</code> 之间的关系?</p> 
 <ul> 
  <li> <strong>Firefox</strong>中这两组属性始终相等,但大小代表的是文档内容区域的实际尺寸,非视口尺寸</li> 
  <li> <strong>Opera Safari Chrome</strong>中这两组属性有区别,其中<code>scrollWidth</code> 和<code>scrollHeight</code> 等于视口大小,而<code>clientWidth</code> 和<code>clientHeight</code> 等于文档内容区域的大小。</li> 
  <li> <strong>IE(在标准模式)</strong>中的这两组属性不相等,其中<code>scrollWidth</code> 和<code>scrollHeight</code> 等于文档内容区域的大小,而<code>clientWidth</code> 和<code>clientHeight</code> 等于视口大小。</li> 
 </ul> 
 <p>通过<code>scrollLeft</code> 和<code>scrollTop</code> 属性既可以确定元素当前滚动的状态,也可以设置元素的滚动位置。在元素尚未被滚动时,这两个属性的值都等于0。如果元素被垂直滚动了,那么<code>scrollTop</code> 的值会大于0,且表示元素上方不可见内容的像素高度。如果元素被水平滚动了,那么<code>scrollLeft</code> 的值会大于0,且表示元素左侧不可见内容的像素宽度。这两个属性都是可以设置的,因此将元素的<code>scrollLeft</code> 和<code>scrollTop</code> 设置为0,就可以重置元素的滚动位置。下面这个函数会检测元素是否位于顶部,如果不是就将其回滚到顶部。</p> 
 <pre><code>function scrollToTop(element){
    if (element.scrollTop != 0){
        element.scrollTop = 0;
    }
}
</code></pre> 
 <h4>确定元素大小</h4> 
 <ul> 
  <li> <code>getBoundingClientRect()</code>方法,会返回一个矩形对象,包含<code>left top right bottom</code>四个属性。这些属性给出了元素在页面中相对于视口的位置。</li> 
 </ul> 
 <h3>遍历</h3> 
 <h4>NodeIterator</h4> 
 <p>可以使用<code>document.createNodeIterator()</code>方法创建它的新实例,接受4个参数。</p> 
 <ul> 
  <li> <code>root</code>:想要作为搜索起点的树中的节点</li> 
  <li> <code>whatToShow</code>:表示要访问哪些节点的数字代码</li> 
  <li> <code>filter</code>:是一个<code>NodeFilter</code>对象,或者一个表示应该接受还是拒绝某种特定节点的函数</li> 
  <li> <code>entityReferenceExpansion</code>:布尔值,表示是否要扩展实体引用。</li> 
 </ul> 
 <p><code>whatToShow</code>这个参数的值以常量形式在<code>NodeFilter</code>类型中定义:</p> 
 <ul> 
  <li><code>NodeFilter.SHOW_ALL</code></li> 
  <li><code>NodeFilter.SHOW_ELEMENT</code></li> 
  <li><code>NodeFilter.SHOW_ATTRIBUTE</code></li> 
  <li><code>NodeFilter.SHOW_TEXT</code></li> 
  <li><code>NodeFilter.SHOW_CDATA_SECTION</code></li> 
  <li><code>NodeFilter.SHOW_ENTITY_REFERENCE</code></li> 
  <li><code>NodeFilter.SHOW_ENTITYE</code></li> 
  <li><code>NodeFilter.SHOW_PROCESSING_INSTRUCTION</code></li> 
  <li><code>NodeFilter.SHOW_COMMENT</code></li> 
  <li><code>NodeFilter.SHOW_DOCUMENT</code></li> 
  <li><code>NodeFilter.SHOW_DOCUMENT_TYPE</code></li> 
  <li><code>NodeFilter.SHOW_DOCUMENT_FRAGMENT</code></li> 
  <li><code>NodeFilter.SHOW_NOTATION</code></li> 
 </ul> 
</article>
                            </div>
                        </div>
                    </div>
                    <!--PC和WAP自适应版-->
                    <div id="SOHUCS" sid="1186040233372786688"></div>
                    <script type="text/javascript" src="/views/front/js/chanyan.js"></script>
                    <!-- 文章页-底部 动态广告位 -->
                    <div class="youdao-fixed-ad" id="detail_ad_bottom"></div>
                </div>
                <div class="col-md-3">
                    <div class="row" id="ad">
                        <!-- 文章页-右侧1 动态广告位 -->
                        <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_1"> </div>
                        </div>
                        <!-- 文章页-右侧2 动态广告位 -->
                        <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_2"></div>
                        </div>
                        <!-- 文章页-右侧3 动态广告位 -->
                        <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad">
                            <div class="youdao-fixed-ad" id="detail_ad_3"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="container">
        <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(JS红宝书·读书笔记 -- 上篇)</h4>
        <div id="paradigm-article-related">
            <div class="recommend-post mb30">
                <ul class="widget-links">
                    <li><a href="/article/1943992018892025856.htm"
                           title="JSON 与 AJAX" target="_blank">JSON 与 AJAX</a>
                        <span class="text-muted">Auscy</span>
<a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/ajax/1.htm">ajax</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>一、JSON(JavaScriptObjectNotation)1.数据类型与语法细节支持的数据类型:基本类型:字符串(需用双引号)、数字、布尔值(true/false)、null。复杂类型:数组([])、对象({})。严格语法规范:键名必须用双引号包裹(如"name":"张三")。数组元素用逗号分隔,最后一个元素后不能有多余逗号。数字不能以0开头(如012会被解析为12),不支持八进制/十六进制</div>
                    </li>
                    <li><a href="/article/1943987101301272576.htm"
                           title="精通Canvas:15款时钟特效代码实现指南" target="_blank">精通Canvas:15款时钟特效代码实现指南</a>
                        <span class="text-muted">烟幕缭绕</span>

                        <div>本文还有配套的精品资源,点击获取简介:HTML5的Canvas是一个用于绘制矢量图形的API,通过JavaScript实现动态效果。本项目集合了15种不同的时钟特效代码,帮助开发者通过学习绘制圆形、线条、时间更新、旋转、颜色样式设置及动画效果等概念,深化对Canvas的理解和应用。项目中的CSS文件负责时钟的样式设定,而JS文件则包含实现各种特效的逻辑,通过不同的函数或类处理时间更新和动画绘制,提</div>
                    </li>
                    <li><a href="/article/1943979911370829824.htm"
                           title="Cesium加载各类数据总结" target="_blank">Cesium加载各类数据总结</a>
                        <span class="text-muted">zhu_zhu_xia</span>
<a class="tag" taget="_blank" href="/search/cesium/1.htm">cesium</a><a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a>
                        <div>接触到的加载数据类型:源地图、shp、Geojson、png、wms、地形底图一.Cesium加载各类底图#此类加载的本质在于newCesium.ImageryProvider()Apidefination:“Providesimagerytobedisplayedonthesurfaceofanellipsoid.Thistypedescribesaninterfaceandisnotinten</div>
                    </li>
                    <li><a href="/article/1943978399890468864.htm"
                           title="如何解决 NPM proxy, 当我们在终端nodejs应用程序时出现代理相关报错" target="_blank">如何解决 NPM proxy, 当我们在终端nodejs应用程序时出现代理相关报错</a>
                        <span class="text-muted"></span>

                        <div>Thisisaproblemrelatedtonetworkconnectivity.npmERR!networkInmostcasesyouarebehindaproxyorhavebadnetworksettings.在使用npminstall下载包的时候总是报以下错误:在控制台或VisualStudioCode终端中运行以下命令:npmconfigrmproxynpmconfigrmhttp</div>
                    </li>
                    <li><a href="/article/1943969574231797760.htm"
                           title="npm 切换 node 版本 和npm的源" target="_blank">npm 切换 node 版本 和npm的源</a>
                        <span class="text-muted">爱敲代码的小冰</span>
<a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/node.js/1.htm">node.js</a>
                        <div>在开发过程中,不同项目可能需要不同版本的Node.js,同时于由XX原因,我们需要切换npm的源。这时如果需要切换node版本或者npm的源,我们可以使用以下方法。使用nvm切换Node版本1、安装npminstallnvm-g2、使用#列出所有可用版本nvmlist-remote#安装指定版本nvminstall16.15.1#使用指定版本nvmuse16.15.1#查看当前使用的版本nvmcu</div>
                    </li>
                    <li><a href="/article/1943968187645227008.htm"
                           title="Kafka系列之:Dead Letter Queue死信队列DLQ" target="_blank">Kafka系列之:Dead Letter Queue死信队列DLQ</a>
                        <span class="text-muted">快乐骑行^_^</span>
<a class="tag" taget="_blank" href="/search/Kafka/1.htm">Kafka</a><a class="tag" taget="_blank" href="/search/Kafka%E7%B3%BB%E5%88%97/1.htm">Kafka系列</a><a class="tag" taget="_blank" href="/search/Dead/1.htm">Dead</a><a class="tag" taget="_blank" href="/search/Letter/1.htm">Letter</a><a class="tag" taget="_blank" href="/search/Queue/1.htm">Queue</a><a class="tag" taget="_blank" href="/search/%E6%AD%BB%E4%BF%A1%E9%98%9F%E5%88%97/1.htm">死信队列</a><a class="tag" taget="_blank" href="/search/DLQ/1.htm">DLQ</a>
                        <div>Kafka系列之:DeadLetterQueue死信队列DLQ一、死信队列二、参数errors.tolerance三、创建死信队列主题四、在启用安全性的情况下使用死信队列更多内容请阅读博主这篇博客:Kafka系列之:KafkaConnect深入探讨-错误处理和死信队列一、死信队列死信队列(DLQ)仅适用于接收器连接器。当一条记录以JSON格式到达接收器连接器时,但接收器连接器配置期望另一种格式,如</div>
                    </li>
                    <li><a href="/article/1943963145055825920.htm"
                           title="react-native android 环境搭建" target="_blank">react-native android 环境搭建</a>
                        <span class="text-muted"></span>

                        <div>环境:macjava版本:Java11最重要:一定要一定要一定要react涉及到很多的依赖下载,gradle和react相关的,第一次安装环境时有外网环境会快速很多。安装nodejs安装react-nativenpminstallreact-native-clinpminstallreact-native创建一个新项目react-nativeinitfirstReact替换gradle下载源rep</div>
                    </li>
                    <li><a href="/article/1943957596671111168.htm"
                           title="docker0网卡没有ip一步解决" target="_blank">docker0网卡没有ip一步解决</a>
                        <span class="text-muted">ξ流ぁ星ぷ132</span>
<a class="tag" taget="_blank" href="/search/tcp%2Fip/1.htm">tcp/ip</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E7%BB%9C/1.htm">网络</a><a class="tag" taget="_blank" href="/search/%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">服务器</a>
                        <div>正常查看ip的时候一直显示没有ip这里先删除docker0网卡iplinkdeletedocker0然后重启服务systemctlrestartdocker再次查看显示有ip了并且查看配置文件也是正常的cat/etc/docker/daemon.json{"registry-mirrors":["https://docker.m.daocloud.io","https://docker.imgdb</div>
                    </li>
                    <li><a href="/article/1943946255763828736.htm"
                           title="《Java前端开发全栈指南:从Servlet到现代框架实战》" target="_blank">《Java前端开发全栈指南:从Servlet到现代框架实战》</a>
                        <span class="text-muted"></span>

                        <div>前言在当今Web开发领域,Java依然是后端开发的主力语言,而随着前后端分离架构的普及,Java开发者也需要掌握前端技术栈。本文将全面介绍JavaWeb前端开发的核心技术,包括传统Servlet/JSP体系、现代前端框架集成方案,以及全栈开发的最佳实践。通过本文,您将了解如何构建现代化的JavaWeb应用前端界面。一、JavaWeb前端技术演进1.1传统技术栈Servlet:JavaWeb基础,处</div>
                    </li>
                    <li><a href="/article/1943941718281875456.htm"
                           title="pythonjson中list操作_Python json.dumps 特殊数据类型的自定义序列化操作" target="_blank">pythonjson中list操作_Python json.dumps 特殊数据类型的自定义序列化操作</a>
                        <span class="text-muted"></span>

                        <div>场景描述:Python标准库中的json模块,集成了将数据序列化处理的功能;在使用json.dumps()方法序列化数据时候,如果目标数据中存在datetime数据类型,执行操作时,会抛出异常:TypeError:datetime.datetime(2016,12,10,11,04,21)isnotJSONserializable那么遇到json.dumps序列化不支持的数据类型,该怎么办!首先,</div>
                    </li>
                    <li><a href="/article/1943940206172368896.htm"
                           title="Python 日期格式转json.dumps的解决方法" target="_blank">Python 日期格式转json.dumps的解决方法</a>
                        <span class="text-muted">douyaoxin</span>
<a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>classDateEncoder(json.JSONEncoder):defdefault(self,obj):ifisinstance(obj,datetime.datetime):returnobj.strftime('%Y-%m-%d%H:%M:%S')elifisinstance(obj,datetime.date):returnobj.strftime("%Y-%m-%d")json.d</div>
                    </li>
                    <li><a href="/article/1943933782121836544.htm"
                           title="Flutter——数据库Drift开发详细教程(七)" target="_blank">Flutter——数据库Drift开发详细教程(七)</a>
                        <span class="text-muted">怀君</span>
<a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/flutter/1.htm">flutter</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">数据库</a>
                        <div>目录入门设置漂移文件入门变量数组定义表支持的列类型漂移特有的功能导入嵌套结果LIST子查询Dart互操作SQL中的Dart组件类型转换器现有的行类Dart文档注释结果类名称支持的语句自定义SQL类型定义类型使用自定义类型在Dart中在SQL中方言意识支持的SQLite扩展json1fts5地缘垄断自定义查询带有生成的api的语句自定义选择语句自定义更新语句入门Drift提供了一个dart_api来</div>
                    </li>
                    <li><a href="/article/1943932016164663296.htm"
                           title="Vue3组件库实战: 打造高复用UI系统" target="_blank">Vue3组件库实战: 打造高复用UI系统</a>
                        <span class="text-muted">武昌库里写JAVA</span>
<a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%B1%87%E6%80%BB%E4%B8%8E%E8%A7%A3%E6%9E%90/1.htm">面试题汇总与解析</a><a class="tag" taget="_blank" href="/search/%E8%AF%BE%E7%A8%8B%E8%AE%BE%E8%AE%A1/1.htm">课程设计</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/layui/1.htm">layui</a><a class="tag" taget="_blank" href="/search/%E6%AF%95%E4%B8%9A%E8%AE%BE%E8%AE%A1/1.htm">毕业设计</a>
                        <div>Vue3组件库实战:打造高复用UI系统介绍什么是Vue3组件库在前端开发中,UI组件库是非常重要的一部分。Vue3组件库是基于Vue.js3.x版本开发的一套可用于构建Web应用的UI组件集合,可以帮助开发者快速搭建页面并保证页面的一致性和美观性。目标关键词:Vue3组件库设计与构建设计原则组件库的设计需要遵循一定的原则,比如易用性、可维护性、扩展性等。在设计阶段需要考虑到不同场景的使用,并且保证</div>
                    </li>
                    <li><a href="/article/1943931763084554240.htm"
                           title="自测魅族手机webview加载h5时ul嵌套li标签js失效问题记录" target="_blank">自测魅族手机webview加载h5时ul嵌套li标签js失效问题记录</a>
                        <span class="text-muted">ZhDan91</span>
<a class="tag" taget="_blank" href="/search/%E6%B7%B7%E5%90%88app/1.htm">混合app</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91/1.htm">前端开发</a>
                        <div>自测魅族手机ul嵌套li标签js失效问题:可采用div嵌套option实现样式:.hot_list{width:100%;display:flex;flex-wrap:wrap;justify-content:space-between;}.hot_listoption{text-align:center;width:30%;padding:.16rem.34rem;border:0.1remso</div>
                    </li>
                    <li><a href="/article/1943930629099941888.htm"
                           title="Ubuntu基础(Python虚拟环境和Vue)" target="_blank">Ubuntu基础(Python虚拟环境和Vue)</a>
                        <span class="text-muted">aaiier</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/python/1.htm">python</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a>
                        <div>Python虚拟环境sudoaptinstallpython3python3-venv进入项目目录cdXXX创建虚拟环境python3-mvenvvenv激活虚拟环境sourcevenv/bin/activate退出虚拟环境deactivateVue安装Node.js和npm#安装Node.js和npm(Ubuntu默认仓库可能版本较旧,适合入门)sudoaptinstallnodejsnpm#验</div>
                    </li>
                    <li><a href="/article/1943930248785620992.htm"
                           title="QML与C++相互调用函数并获得返回值" target="_blank">QML与C++相互调用函数并获得返回值</a>
                        <span class="text-muted">cpp_learners</span>
<a class="tag" taget="_blank" href="/search/QML/1.htm">QML</a><a class="tag" taget="_blank" href="/search/c%2B%2B/1.htm">c++</a><a class="tag" taget="_blank" href="/search/QML/1.htm">QML</a><a class="tag" taget="_blank" href="/search/qt/1.htm">qt</a>
                        <div>这篇博客主要讲解在qml端如何直接调用c++的函数并获得返回值,在c++端如何直接调用qml的函数并获得返回值;主要以map或者jsonobject、list或者jsonarray为主!其他单个类型,常见的类型,例如QString、int等,就不演示了;一通百通。目录1准备工作1.1C++端1.2QML端2qml端直接调用c++端函数3c++端直接调用qml端函数3.1调用qml的qmlFuncO</div>
                    </li>
                    <li><a href="/article/1943920666499674112.htm"
                           title="老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)" target="_blank">老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)</a>
                        <span class="text-muted"></span>

                        <div>老系统改造增加初始化,自动化数据源配置一、前言二、改造描述1、环境说明2、实现步骤简要思考三、开始改造1、准备sql初始化文件2、启动时自动读取jdbc文件,创建数据源,如未配置,需要一个默认的临时数据源2.1去掉spingmvc原本配置的固定dataSource,改为动态dataSource2.2代码类,这里是示例,我就不管规范了,放到一起2.2.1DynamicDataSourceConfig</div>
                    </li>
                    <li><a href="/article/1943919909612351488.htm"
                           title="Vue.js 过渡 & 动画" target="_blank">Vue.js 过渡 & 动画</a>
                        <span class="text-muted">lsx202406</span>
<a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>Vue.js过渡&动画引言在Web开发中,过渡与动画是提升用户体验的关键元素。Vue.js作为一款流行的前端框架,提供了强大的过渡与动画功能,使得开发者能够轻松实现丰富的交互效果。本文将深入探讨Vue.js中的过渡与动画,包括其原理、应用场景以及实现方法。一、Vue.js过渡原理Vue.js过渡是利用CSS3的transition属性实现的。当Vue.js侦测到数据变化时,会自动触发过渡效果。过渡</div>
                    </li>
                    <li><a href="/article/1943917893620133888.htm"
                           title="V少JS基础班之第五弹" target="_blank">V少JS基础班之第五弹</a>
                        <span class="text-muted">V少在逆向</span>
<a class="tag" taget="_blank" href="/search/JS%E5%9F%BA%E7%A1%80%E7%8F%AD/1.htm">JS基础班</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a>
                        <div>文章目录一、前言二、本节涉及知识点三、重点内容1-函数的定义2-函数的构成1.函数参数详解1)参数个数不固定2)默认参数3)arguments对象(类数组)4)剩余参数(Rest参数)5)函数参数是按值传递的6)解构参数传递7)参数校验技巧(JavaScript没有类型限制,需要手动校验)2.函数返回值详解3-函数的分类1-函数声明式:2-函数表达式:3-箭头函数:4-构造函数:5-IIFE:6-</div>
                    </li>
                    <li><a href="/article/1943917011268595712.htm"
                           title="Javaweb学习之Vue模板语法(三)" target="_blank">Javaweb学习之Vue模板语法(三)</a>
                        <span class="text-muted">不要数手指啦</span>
<a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%AD%A6%E4%B9%A0/1.htm">学习</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a>
                        <div>目录学习资料前情回顾本期介绍(vue模板语法)文本插值Vue的Attribute绑定使用JavaScript表达式综合实例代码:学习资料Vue.js-渐进式JavaScript框架|Vue.js(vuejs.org)前情回顾项目的创建大家可以看这篇文章Vue学习之项目的创建-CSDN博客本期介绍(vue模板语法)首先,找到我们编写代码的地方找到自己项目的src文件夹,打开之后点击component</div>
                    </li>
                    <li><a href="/article/1943914742187880448.htm"
                           title="Vue3 tailwindcss" target="_blank">Vue3 tailwindcss</a>
                        <span class="text-muted"></span>

                        <div>1、安装tailwindcsspnpmi-Dtailwindcsspostcssautoprefixer#yarnadd-Dtailwindcsspostcssautoprefixer#npmi-Dtailwindcsspostcssautoprefixer2、创建TailwindCSS配置文件npxtailwindcssinit-ptailwind.config.js/**@type{impor</div>
                    </li>
                    <li><a href="/article/1943905285789773824.htm"
                           title="three前置课程知识" target="_blank">three前置课程知识</a>
                        <span class="text-muted"></span>

                        <div>学习中文网(1.threejs文件包下载和目录简介|Three.js中文网)threejs官方文件包所有版本:https://github.com/mrdoob/three.js/releases更新迭代较快,要选择对应版本使用---下载zip压缩包Threejs官网中文文档链接:https://threejs.org/docs/index.html#manual/zh/重要的内容docs包:文档</div>
                    </li>
                    <li><a href="/article/1943887012146769920.htm"
                           title="Ubuntu 安装 RAGFlow 简单流程" target="_blank">Ubuntu 安装 RAGFlow 简单流程</a>
                        <span class="text-muted">steven_41936912</span>
<a class="tag" taget="_blank" href="/search/ubuntu/1.htm">ubuntu</a><a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a><a class="tag" taget="_blank" href="/search/RAGFlow/1.htm">RAGFlow</a>
                        <div>Docker拉取镜像慢可以更换镜像源sudotee/etc/docker/daemon.json<<-'EOF'{"registry-mirrors":["https://docker.m.daocloud.io","https://docker.imgdb.de","https://docker-0.unsee.tech","https://docker.hlmirror.com","https</div>
                    </li>
                    <li><a href="/article/1943875785089675264.htm"
                           title="Webpack5 多页面实践" target="_blank">Webpack5 多页面实践</a>
                        <span class="text-muted"></span>

                        <div>特性维度单页面应用-SPA多页面统一目录-MPA多页面单独部署-MPA入口数量单个,只有一个HTML文件多个,多个HTML文件多个,多个HTML文件,分别打包输出资源输出结构所有资源输出到统一目录(如js/,css/)所有页面的资源共用js/,css/等目录每页资源放在各自目录(如index/js/,index/css/)公共资源复用高:依赖打入主包或懒加载chunk,资源完全共享中:可通过spl</div>
                    </li>
                    <li><a href="/article/1943855613205344256.htm"
                           title="Spring 如何干预 Bean 的生命周期?" target="_blank">Spring 如何干预 Bean 的生命周期?</a>
                        <span class="text-muted">冰糖心书房</span>
<a class="tag" taget="_blank" href="/search/Spring/1.htm">Spring</a><a class="tag" taget="_blank" href="/search/IOC/1.htm">IOC</a><a class="tag" taget="_blank" href="/search/Ioc/1.htm">Ioc</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/Bean/1.htm">Bean</a><a class="tag" taget="_blank" href="/search/%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/1.htm">生命周期</a>
                        <div>Spring提供了多种机制让我们能够在Bean生命周期的不同节点“插入”自己的逻辑,这些机制可以分为两大类:针对单个Bean的干预和针对所有/多个Bean的全局干预。一、针对单个Bean的干预(最常用)这些方法让你为一个特定的Bean类定义其初始化和销毁逻辑。1.使用JSR-250注解(推荐方式)这是现在最优雅、也是Spring官方推荐的方式。它使用Java的标准注解,与Spring框架解耦。@P</div>
                    </li>
                    <li><a href="/article/1943853592725221376.htm"
                           title="GPT实操——利用GPT创建一个应用" target="_blank">GPT实操——利用GPT创建一个应用</a>
                        <span class="text-muted">狗木马</span>
<a class="tag" taget="_blank" href="/search/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/1.htm">深度学习</a><a class="tag" taget="_blank" href="/search/gpt-3/1.htm">gpt-3</a><a class="tag" taget="_blank" href="/search/gpt/1.htm">gpt</a>
                        <div>功能描述信息查询:用户可以询问各种问题,如天气、新闻、股票等,机器人会返回相关信息。任务执行:用户可以要求机器人执行一些简单的任务,如设置提醒、发送邮件等。情感支持:机器人可以与用户进行情感交流,提供安慰和支持。个性化设置:用户可以自定义机器人的回复风格和偏好。技术栈前端:React.js后端:Node.js+Express数据库:MongoDB自然语言处理:OpenAIGPT-3API其他工具:</div>
                    </li>
                    <li><a href="/article/1943848300524400640.htm"
                           title="【JS三兄弟谁是谁】搞懂 splice、slice、split,只需一杯奶茶的时间!" target="_blank">【JS三兄弟谁是谁】搞懂 splice、slice、split,只需一杯奶茶的时间!</a>
                        <span class="text-muted">dorabighead</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%85%AB%E8%82%A1%E6%80%BB%E7%BB%93/1.htm">前端八股总结</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>JavaScript有三兄弟,经常一起“切人”。他们名字相似、功能相关,但性格迥异,常被搞混。今天,就带你喝着奶茶,笑着剖析,帮你彻底搞懂:splice、slice、split到底是谁?干了啥?凭啥这么火?一、三兄弟登场:不同对象,不同任务名称作用对象是否修改原对象返回类型功能简述splice数组✅是被删除元素数组原地删除元素并可插入新元素slice数组/字符串❌否副本(子集)复制选中部分,原体不</div>
                    </li>
                    <li><a href="/article/1943847416503529472.htm"
                           title="前端面试题总结——JS篇" target="_blank">前端面试题总结——JS篇</a>
                        <span class="text-muted">又又呢</span>
<a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a>
                        <div>一、说说JavaScript中的数据类型?存储上有什么差别?1、数据类型基本类型number:数值类型十进制:letintNum=55八进制(零开头):letnum1=070十六进制(0x开头):lethexNum1=0xANaN:特殊数值,意为“不是数值”string:字符串类型boolean:布尔值,true或falseundefined:表示未定义null:空值symbol:是原始值,且符号</div>
                    </li>
                    <li><a href="/article/1943842998383079424.htm"
                           title="2023高薪前端面试题(二、前端核心——Ajax)" target="_blank">2023高薪前端面试题(二、前端核心——Ajax)</a>
                        <span class="text-muted"></span>

                        <div>原生AjaxAjax简介Ajax全程为AsynchronousJavaScript+XML,就是异步的JS和XML通过AJAX可以在浏览器中向服务器发送异步请求,最大的优势是:无刷新获取数据,实现局部刷新Ajax是一种用于创建快速动态网页的技术AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式Ajax的应用场景页面上拉加载更多数据列表数据无刷新分页表单项离开焦点数据验证搜索框提示</div>
                    </li>
                    <li><a href="/article/1943839971936890880.htm"
                           title="Elasticsearch混合搜索深度解析(下):执行机制与完整流程" target="_blank">Elasticsearch混合搜索深度解析(下):执行机制与完整流程</a>
                        <span class="text-muted">GeminiJM</span>
<a class="tag" taget="_blank" href="/search/ES%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">ES学习笔记</a><a class="tag" taget="_blank" href="/search/elasticsearch/1.htm">elasticsearch</a><a class="tag" taget="_blank" href="/search/jenkins/1.htm">jenkins</a><a class="tag" taget="_blank" href="/search/%E5%A4%A7%E6%95%B0%E6%8D%AE/1.htm">大数据</a>
                        <div>引言在上篇中,我们发现了KNN结果通过SubSearch机制被保留的关键事实。本篇将继续深入分析混合搜索的执行机制,揭示完整的处理流程,并解答之前的所有疑惑。深入源码分析1.SubSearch的执行机制1.1KnnScoreDocQueryBuilder的实现KNN结果被转换为KnnScoreDocQueryBuilder,这个类负责在查询阶段重新执行KNN搜索://server/src/main</div>
                    </li>
                                <li><a href="/article/17.htm"
                                       title="分享100个最新免费的高匿HTTP代理IP" target="_blank">分享100个最新免费的高匿HTTP代理IP</a>
                                    <span class="text-muted">mcj8089</span>
<a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%90%86IP/1.htm">代理IP</a><a class="tag" taget="_blank" href="/search/%E4%BB%A3%E7%90%86%E6%9C%8D%E5%8A%A1%E5%99%A8/1.htm">代理服务器</a><a class="tag" taget="_blank" href="/search/%E5%8C%BF%E5%90%8D%E4%BB%A3%E7%90%86/1.htm">匿名代理</a><a class="tag" taget="_blank" href="/search/%E5%85%8D%E8%B4%B9%E4%BB%A3%E7%90%86IP/1.htm">免费代理IP</a><a class="tag" taget="_blank" href="/search/%E6%9C%80%E6%96%B0%E4%BB%A3%E7%90%86IP/1.htm">最新代理IP</a>
                                    <div>  
推荐两个代理IP网站: 
  
1. 全网代理IP:http://proxy.goubanjia.com/ 
  
2. 敲代码免费IP:http://ip.qiaodm.com/ 
  
  
120.198.243.130:80,中国/广东省
58.251.78.71:8088,中国/广东省
183.207.228.22:83,中国/</div>
                                </li>
                                <li><a href="/article/144.htm"
                                       title="mysql高级特性之数据分区" target="_blank">mysql高级特性之数据分区</a>
                                    <span class="text-muted">annan211</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/mongodb/1.htm">mongodb</a><a class="tag" taget="_blank" href="/search/%E5%88%86%E5%8C%BA/1.htm">分区</a><a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a>
                                    <div>


mysql高级特性
  1 以存储引擎的角度分析,分区表和物理表没有区别。是按照一定的规则将数据分别存储的逻辑设计。器底层是由多个物理字表组成。
  
  2 分区的原理
     分区表由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们可以直接访问各个分区。存储引擎管理分区的各个底层
	 表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是</div>
                                </li>
                                <li><a href="/article/271.htm"
                                       title="JS采用正则表达式简单获取URL地址栏参数" target="_blank">JS采用正则表达式简单获取URL地址栏参数</a>
                                    <span class="text-muted">chiangfai</span>
<a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/%E5%9C%B0%E5%9D%80%E6%A0%8F%E5%8F%82%E6%95%B0%E8%8E%B7%E5%8F%96/1.htm">地址栏参数获取</a>
                                    <div>GetUrlParam:function GetUrlParam(param){
		var reg = new RegExp("(^|&)"+ param +"=([^&]*)(&|$)");
		var r = window.location.search.substr(1).match(reg);
		if(r!=null</div>
                                </li>
                                <li><a href="/article/398.htm"
                                       title="怎样将数据表拷贝到powerdesigner (本地数据库表)" target="_blank">怎样将数据表拷贝到powerdesigner (本地数据库表)</a>
                                    <span class="text-muted">Array_06</span>
<a class="tag" taget="_blank" href="/search/powerDesigner/1.htm">powerDesigner</a>
                                    <div>================================================== 
 
1、打开PowerDesigner12,在菜单中按照如下方式进行操作 
file->Reverse Engineer->DataBase 
点击后,弹出 New Physical Data Model 的对话框 
2、在General选项卡中 
Model name:模板名字,自</div>
                                </li>
                                <li><a href="/article/525.htm"
                                       title="logbackのhelloworld" target="_blank">logbackのhelloworld</a>
                                    <span class="text-muted">飞翔的马甲</span>
<a class="tag" taget="_blank" href="/search/%E6%97%A5%E5%BF%97/1.htm">日志</a><a class="tag" taget="_blank" href="/search/logback/1.htm">logback</a>
                                    <div>一、概述 
 
1.日志是啥? 
当我是个逗比的时候我是这么理解的:log.debug()代替了system.out.print(); 
当我项目工作时,以为是一堆得.log文件。 
这两天项目发布新版本,比较轻松,决定好好地研究下日志以及logback。 
传送门1:日志的作用与方法: 
http://www.infoq.com/cn/articles/why-and-how-log 
上面的作</div>
                                </li>
                                <li><a href="/article/652.htm"
                                       title="新浪微博爬虫模拟登陆" target="_blank">新浪微博爬虫模拟登陆</a>
                                    <span class="text-muted">随意而生</span>
<a class="tag" taget="_blank" href="/search/%E6%96%B0%E6%B5%AA%E5%BE%AE%E5%8D%9A/1.htm">新浪微博</a>
                                    <div>转载自:http://hi.baidu.com/erliang20088/item/251db4b040b8ce58ba0e1235 
  
  
近来由于毕设需要,重新修改了新浪微博爬虫废了不少劲,希望下边的总结能够帮助后来的同学们。 
     现行版的模拟登陆与以前相比,最大的改动在于cookie获取时候的模拟url的请求</div>
                                </li>
                                <li><a href="/article/779.htm"
                                       title="synchronized" target="_blank">synchronized</a>
                                    <span class="text-muted">香水浓</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/thread/1.htm">thread</a>
                                    <div>    Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然</div>
                                </li>
                                <li><a href="/article/906.htm"
                                       title="maven 简单实用教程" target="_blank">maven 简单实用教程</a>
                                    <span class="text-muted">AdyZhang</span>
<a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a>
                                    <div>1. Maven介绍  1.1. 简介 java编写的用于构建系统的自动化工具。目前版本是2.0.9,注意maven2和maven1有很大区别,阅读第三方文档时需要区分版本。 1.2. Maven资源 见官方网站;The 5 minute test,官方简易入门文档;Getting Started Tutorial,官方入门文档;Build Coo</div>
                                </li>
                                <li><a href="/article/1033.htm"
                                       title="Android 通过 intent传值获得null" target="_blank">Android 通过 intent传值获得null</a>
                                    <span class="text-muted">aijuans</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                    <div>我在通过intent 获得传递兑现过的时候报错,空指针,我是getMap方法进行传值,代码如下        1   2   3   4   5   6   7   8   9      
public 
void 
getMap(View view){       
         
Intent i =</div>
                                </li>
                                <li><a href="/article/1160.htm"
                                       title="apache 做代理 报如下错误:The proxy server received an invalid response from an upstream" target="_blank">apache 做代理 报如下错误:The proxy server received an invalid response from an upstream</a>
                                    <span class="text-muted">baalwolf</span>
<a class="tag" taget="_blank" href="/search/response/1.htm">response</a>
                                    <div>网站配置是apache+tomcat,tomcat没有报错,apache报错是: 
The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET /. Reason: Error reading fr</div>
                                </li>
                                <li><a href="/article/1287.htm"
                                       title="Tomcat6 内存和线程配置" target="_blank">Tomcat6 内存和线程配置</a>
                                    <span class="text-muted">BigBird2012</span>
<a class="tag" taget="_blank" href="/search/tomcat6/1.htm">tomcat6</a>
                                    <div>1、修改启动时内存参数、并指定JVM时区 (在windows server 2008 下时间少了8个小时) 
在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数:  
window下, 在catalina.bat最前面 
  set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms5</div>
                                </li>
                                <li><a href="/article/1414.htm"
                                       title="Karam与TDD" target="_blank">Karam与TDD</a>
                                    <span class="text-muted">bijian1013</span>
<a class="tag" taget="_blank" href="/search/Karam/1.htm">Karam</a><a class="tag" taget="_blank" href="/search/TDD/1.htm">TDD</a>
                                    <div>一.TDD 
        测试驱动开发(Test-Driven Development,TDD)是一种敏捷(AGILE)开发方法论,它把开发流程倒转了过来,在进行代码实现之前,首先保证编写测试用例,从而用测试来驱动开发(而不是把测试作为一项验证工具来使用)。 
        TDD的原则很简单: 
a.只有当某个</div>
                                </li>
                                <li><a href="/article/1541.htm"
                                       title="[Zookeeper学习笔记之七]Zookeeper源代码分析之Zookeeper.States" target="_blank">[Zookeeper学习笔记之七]Zookeeper源代码分析之Zookeeper.States</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/zookeeper/1.htm">zookeeper</a>
                                    <div>    public enum States {
        CONNECTING, //Zookeeper服务器不可用,客户端处于尝试链接状态
        ASSOCIATING, //???
        CONNECTED, //链接建立,可以与Zookeeper服务器正常通信
        CONNECTEDREADONLY, //处于只读状态的链接状态,只读模式可以在</div>
                                </li>
                                <li><a href="/article/1668.htm"
                                       title="【Scala十四】Scala核心八:闭包" target="_blank">【Scala十四】Scala核心八:闭包</a>
                                    <span class="text-muted">bit1129</span>
<a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a>
                                    <div>Free variable A free variable of an expression is a variable that’s used inside the expression but not defined inside the expression. For instance, in the function literal expression (x: Int) => (x</div>
                                </li>
                                <li><a href="/article/1795.htm"
                                       title="android发送json并解析返回json" target="_blank">android发送json并解析返回json</a>
                                    <span class="text-muted">ronin47</span>
<a class="tag" taget="_blank" href="/search/android/1.htm">android</a>
                                    <div>package com.http.test; 
 
 
import org.apache.http.HttpResponse; 
import org.apache.http.HttpStatus; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import </div>
                                </li>
                                <li><a href="/article/1922.htm"
                                       title="一份IT实习生的总结" target="_blank">一份IT实习生的总结</a>
                                    <span class="text-muted">brotherlamp</span>
<a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/php%E8%B5%84%E6%96%99/1.htm">php资料</a><a class="tag" taget="_blank" href="/search/php%E6%95%99%E7%A8%8B/1.htm">php教程</a><a class="tag" taget="_blank" href="/search/php%E5%9F%B9%E8%AE%AD/1.htm">php培训</a><a class="tag" taget="_blank" href="/search/php%E8%A7%86%E9%A2%91/1.htm">php视频</a>
                                    <div>今天突然发现在不知不觉中自己已经实习了 3 个月了,现在可能不算是真正意义上的实习吧,因为现在自己才大三,在这边撸代码的同时还要考虑到学校的功课跟期末考试。让我震惊的是,我完全想不到在这 3 个月里我到底学到了什么,这是一件多么悲催的事情啊。同时我对我应该 get 到什么新技能也很迷茫。所以今晚还是总结下把,让自己在接下来的实习生活有更加明确的方向。最后感谢工作室给我们几个人这个机会让我们提前出来</div>
                                </li>
                                <li><a href="/article/2049.htm"
                                       title="据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码" target="_blank">据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码</a>
                                    <span class="text-muted">bylijinnan</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a>
                                    <div>
public class ScalesBalance {

	/**
	 * 题目:
	 * 给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 (假设N无限大,但一种重量的砝码只有一个)
	 * 将重物放到天平左侧,问在两边如何添加砝码使两边平衡
	 * 
	 * 分析:
	 * 三进制
	 * 我们约定括号表示里面的数是三进制,例如 47=(1202</div>
                                </li>
                                <li><a href="/article/2176.htm"
                                       title="dom4j最常用最简单的方法" target="_blank">dom4j最常用最简单的方法</a>
                                    <span class="text-muted">chiangfai</span>
<a class="tag" taget="_blank" href="/search/dom4j/1.htm">dom4j</a>
                                    <div>要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/目前最新dom4j包下载地址:http://nchc.dl.sourceforge.net/sourceforge/dom4j/dom4j-1.6.1.zip 
解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要</div>
                                </li>
                                <li><a href="/article/2303.htm"
                                       title="简单HBase笔记" target="_blank">简单HBase笔记</a>
                                    <span class="text-muted">chenchao051</span>
<a class="tag" taget="_blank" href="/search/hbase/1.htm">hbase</a>
                                    <div> 一、Client-side write buffer 客户端缓存请求   描述:可以缓存客户端的请求,以此来减少RPC的次数,但是缓存只是被存在一个ArrayList中,所以多线程访问时不安全的。   可以使用getWriteBuffer()方法来取得客户端缓存中的数据。 默认关闭。      二、Scan的Caching   描述: next( )方法请求一行就要使用一次RPC,即使</div>
                                </li>
                                <li><a href="/article/2430.htm"
                                       title="mysqldump导出时出现when doing LOCK TABLES" target="_blank">mysqldump导出时出现when doing LOCK TABLES</a>
                                    <span class="text-muted">daizj</span>
<a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/mysqdump/1.htm">mysqdump</a><a class="tag" taget="_blank" href="/search/%E5%AF%BC%E6%95%B0%E6%8D%AE/1.htm">导数据</a>
                                    <div>  执行 mysqldump -uxxx -pxxx -hxxx -Pxxxx database tablename > tablename.sql  
导出表时,会报 
 
mysqldump: Got error: 1044: Access denied for user 'xxx'@'xxx' to database 'xxx' when doing LOCK TABLES 
 
解决</div>
                                </li>
                                <li><a href="/article/2557.htm"
                                       title="CSS渲染原理" target="_blank">CSS渲染原理</a>
                                    <span class="text-muted">dcj3sjt126com</span>
<a class="tag" taget="_blank" href="/search/Web/1.htm">Web</a>
                                    <div>   从事Web前端开发的人都与CSS打交道很多,有的人也许不知道css是怎么去工作的,写出来的css浏览器是怎么样去解析的呢?当这个成为我们提高css水平的一个瓶颈时,是否应该多了解一下呢?   
  
       一、浏览器的发展与CSS      
  
   </div>
                                </li>
                                <li><a href="/article/2684.htm"
                                       title="《阿甘正传》台词" target="_blank">《阿甘正传》台词</a>
                                    <span class="text-muted">dcj3sjt126com</span>

                                    <div>Part Ⅰ: 
《阿甘正传》Forrest Gump经典中英文对白 
Forrest: Hello! My names Forrest. Forrest Gump. You wanna Chocolate? I could eat about a million and a half othese. My momma always said life was like a box ochocol</div>
                                </li>
                                <li><a href="/article/2811.htm"
                                       title="Java处理JSON" target="_blank">Java处理JSON</a>
                                    <span class="text-muted">dyy_gusi</span>
<a class="tag" taget="_blank" href="/search/json/1.htm">json</a>
                                    <div>Json在数据传输中很好用,原因是JSON 比 XML 更小、更快,更易解析。 
在Java程序中,如何使用处理JSON,现在有很多工具可以处理,比较流行常用的是google的gson和alibaba的fastjson,具体使用如下: 
1、读取json然后处理 
class ReadJSON
{
    public static void main(String[] args)
    </div>
                                </li>
                                <li><a href="/article/2938.htm"
                                       title="win7下nginx和php的配置" target="_blank">win7下nginx和php的配置</a>
                                    <span class="text-muted">geeksun</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a>
                                    <div>1.  安装包准备 
nginx :  从nginx.org下载nginx-1.8.0.zip 
php: 从php.net下载php-5.6.10-Win32-VC11-x64.zip, php是免安装文件。 
RunHiddenConsole: 用于隐藏命令行窗口 
  
2. 配置 
# java用8080端口做应用服务器,nginx反向代理到这个端口即可 
p</div>
                                </li>
                                <li><a href="/article/3065.htm"
                                       title="基于2.8版本redis配置文件中文解释" target="_blank">基于2.8版本redis配置文件中文解释</a>
                                    <span class="text-muted">hongtoushizi</span>
<a class="tag" taget="_blank" href="/search/redis/1.htm">redis</a>
                                    <div>转载自: http://wangwei007.blog.51cto.com/68019/1548167 
       在Redis中直接启动redis-server服务时, 采用的是默认的配置文件。采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务。下面是Redis2.8.9的配置文</div>
                                </li>
                                <li><a href="/article/3192.htm"
                                       title="第五章 常用Lua开发库3-模板渲染" target="_blank">第五章 常用Lua开发库3-模板渲染</a>
                                    <span class="text-muted">jinnianshilongnian</span>
<a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/lua/1.htm">lua</a>
                                    <div>动态web网页开发是Web开发中一个常见的场景,比如像京东商品详情页,其页面逻辑是非常复杂的,需要使用模板技术来实现。而Lua中也有许多模板引擎,如目前我在使用的lua-resty-template,可以渲染很复杂的页面,借助LuaJIT其性能也是可以接受的。 
  
如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;而lua-r</div>
                                </li>
                                <li><a href="/article/3319.htm"
                                       title="JZSearch大数据搜索引擎" target="_blank">JZSearch大数据搜索引擎</a>
                                    <span class="text-muted">颠覆者</span>
<a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a>
                                    <div>系统简介: 
 
 大数据的特点有四个层面:第一,数据体量巨大。从TB级别,跃升到PB级别;第二,数据类型繁多。网络日志、视频、图片、地理位置信息等等。第三,价值密度低。以视频为例,连续不间断监控过程中,可能有用的数据仅仅有一两秒。第四,处理速度快。最后这一点也是和传统的数据挖掘技术有着本质的不同。业界将其归纳为4个“V”——Volume,Variety,Value,Velocity。大数据搜索引</div>
                                </li>
                                <li><a href="/article/3446.htm"
                                       title="10招让你成为杰出的Java程序员" target="_blank">10招让你成为杰出的Java程序员</a>
                                    <span class="text-muted">pda158</span>
<a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B/1.htm">编程</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a>
                                    <div>如果你是一个热衷于技术的  
Java 程序员, 那么下面的 10 个要点可以让你在众多 Java 开发人员中脱颖而出。      
1. 拥有扎实的基础和深刻理解 OO 原则     对于 Java 程序员,深刻理解 Object Oriented Programming(面向对象编程)这一概念是必须的。没有 OOPS 的坚实基础,就领会不了像 Java 这些面向对象编程语言</div>
                                </li>
                                <li><a href="/article/3573.htm"
                                       title="tomcat之oracle连接池配置" target="_blank">tomcat之oracle连接池配置</a>
                                    <span class="text-muted">小网客</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a>
                                    <div>tomcat版本7.0 
配置oracle连接池方式: 
修改tomcat的server.xml配置文件: 
 <GlobalNamingResources>
 
			  <Resource name="utermdatasource" auth="Container"  
 type="javax.sql.DataSou</div>
                                </li>
                                <li><a href="/article/3700.htm"
                                       title="Oracle 分页算法汇总" target="_blank">Oracle 分页算法汇总</a>
                                    <span class="text-muted">vipbooks</span>
<a class="tag" taget="_blank" href="/search/oracle/1.htm">oracle</a><a class="tag" taget="_blank" href="/search/sql/1.htm">sql</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/.net/1.htm">.net</a>
                                    <div>    这是我找到的一些关于Oracle分页的算法,大家那里还有没有其他好的算法没?我们大家一起分享一下! 
 
 

-- Oracle 分页算法一
select * from (
       select page.*,rownum rn from (select * from help) page 
       -- 20 = (currentPag</div>
                                </li>
                </ul>
            </div>
        </div>
    </div>

<div>
    <div class="container">
        <div class="indexes">
            <strong>按字母分类:</strong>
            <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a
                href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a
                href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a
                href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a
                href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a
                href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a
                href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a
                href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a
                href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a>
        </div>
    </div>
</div>
<footer id="footer" class="mb30 mt30">
    <div class="container">
        <div class="footBglm">
            <a target="_blank" href="/">首页</a> -
            <a target="_blank" href="/custom/about.htm">关于我们</a> -
            <a target="_blank" href="/search/Java/1.htm">站内搜索</a> -
            <a target="_blank" href="/sitemap.txt">Sitemap</a> -
            <a target="_blank" href="/custom/delete.htm">侵权投诉</a>
        </div>
        <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved.
<!--            <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>-->
        </div>
    </div>
</footer>
<!-- 代码高亮 -->
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script>
<script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script>
<link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/>
<script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script>





</body>

</html>