JavaScript学习笔记
自己看了觉得值得推荐的书:
《JavaScript高级程序设计》
《深入理解JavaScript》
《JavaScript面向对象精要》
《JavaScript权威指南》类似API书,适合查漏补缺
其他参考书:
《JavaScript语言精粹》
《高性能JavaScript》
《JavaScript设计模式》
《编写可维护的JavaScript》
《你不知道的JS(上卷)》
《你不知道的JS(中卷)》
《你不知道的JS(下卷)》
(因为我的OneNote笔记粘贴到网页图片无法显示,所以后续将修整)
本笔记导航:
ES5
开始支持:
严格模式
原生JSON对象
Features include Function.prototype.bind,
Array methods like indexOf, forEach, map & filter,
Object methods like defineProperty, create & keys,
the trim method on Strings and many more.
js基础知识
(基本数据类型)原始类型:boolean, number, string, null, undefined,symbol(ES6)
内置对象:Number, String, Boolean , Object,Array,Function,Argument,Date, RegExp, Math, Error。
JavaScript包括核心(ECMAScript)、文档对象模型(DOM)、浏览器对象模型(BOM)
Javascript=ECMAScript+DOM+BOM
宿主环境有浏览器、Node和Adobe Flash 。
ECMA-262标准规定了语言的下列组成部分:语法、类型、语句、关键字、保留字、操作符、对象。
DOM
规定的是如何映射于XML的文档结构,以便简化对文档中任意部分的访问和操作。
针对HTML的对象和方法。
事件
样式
遍历和范围
SVG(Scalable Vector Graphic, 可伸缩向量图形)等
BOM
弹出新浏览器窗口的功能
移动、缩放和关闭浏览器窗口的功能
navigator对象
location
screen
cookies
XMLHTTPRequest和IE的ActiveXObject这样的自定义对象
window
” 字 符 串 。 例 如 , 浏 览 器 在 加 载 下 面 所 示 的 代 码 时 就 会 产 生 一 个 锚 误 : function 010rt ( “ / •cript , , ) C/scrip'* 因 为 按 照 解 析 嵌 人 式 代 码 的 規 则 , 当 浏 览 器 遇 到 字 符 串 “ < / “ p [ 时 , 就 会 认 为 那 是 结 束 的 e/script>-% 签 。 而 通 过 把 这 个 字 符 串 分 隔 为 两 部 分 可 以 解 决 这 个 问 题 . 例 如 : " v:shapes="图片_x0020_218">
在JavaScript中所有的值都有属性。每一个属性都有一个key(或者是name)
和一个value。可以认为,属性就像是一条记录的字段。通过点(.)操作符可以读
取属性、赋值。
var objl = {l; > var 0 习 2 = O; / / an empty object / / another empty object > 0b 〕 1 > 0b 」 1 0b 」 2 0b 〕 1 相 反 , 所 有 的 原 始 值 , 只 要 编 码 值 相 同 , 则 被 认 为 相 等 : 、 var pri , 1 = 123 ; > var prim2 = 123 ; 、 priml = = = 豇 2 " v:shapes="图片_x0020_217">
console.log(typeof null); //object, null是一个空的对象指针。
判断一个值是否为空类型:value===null
使用===,是因为三等号在比较时不会将变量强制转换为另一种类型。
(==会把字符串转换成数字)
string 虽然是原始类型,但也有方法:
console.log(typeof null); // object,null是一个空的对象指针,也可以认为是一个bug
console.log("5" === 5); // true
console.log(undefined==null); // 注意三等号会强制类型转换
var name = "Beth_Chan";
console.log(name.toLowerCase(),name.charAt(0),name.substring(2,5)); // 注意驼峰;索引从0开始;第二个索引不能算进去(左闭右开区间)
var count = 10;
console.log(count.toFixed(2),count.toString(8),count.toString(16)); // 10.00;10转换成八进制是12,转换成十六进制是a
var flag = true;
console.log(flag.toString()); // true
创建对象:
new Object() // new操作符和,=构造函数 指向内存中实际对象所在的指针(或者说引用)
内置(内建build-in)对象:Object,Function,Array,Date,Error,RegExp
对象字面形式创建对象,可以在大括号中定义一个新对象及其属性,属性的组成包括一个标识符或字符串、一个冒号以及一个值,多个属性之间用逗号隔开。
字面形式并没有调用new Object(),但JavaScript引擎背后做的工作与new Object()一样。
数组用中括号。
JavaScript有垃圾收集功能,使用引用类型时无需担心内存分配。解除引用是将对象变量置为null。
对象可随时添加和删除属性。
通常不会有人使用函数的构造函数。
允许用字面形式而不是使用RegExp构造函数定义正则表达式。
(类似Perl)
模式被包含在两个“/“之间,第二个”/“后是由单字符表示的额外选项。
使用字面形式不需要担心字符串中的转义字符。
除非需要通过一个或多个字符串动态构造正则表达式,否则建议字面形式。
function reflect(value) {
return value;
}
console.log(typeof reflect); // function;对于其他非函数的引用类型,typeof都是返回“object”
var items = [];
var object = {};
function reflect(value) {
return value;
}
// instanceof以一个对象和一个构造函数为参数
console.log(items instanceof Array);
console.log(items instanceof Object);
console.log(object instanceof Array); // false
console.log(object instanceof Object);
console.log(reflect instanceof Function);
console.log(reflect instanceof Object);
// 所有引用类型都继承自Object,即所有对象都是Object的实例
Array.isArray(items); // true;鉴别数组(把一个数组从一个框架传到另一个框架时,全局上下文不同,所以instanceof无法识别);IE8及更早的版本不支持。
属性是对象中保存的名字和值的配对。
点号或中括号(要有引号)均可访问属性。例如array.push(123)可以写成array["push"](123)。
动态访问哪个属性或者属性名字有特殊字符时,特别有用。var method = "push"; array[method] (123)。
原始封装类型
原始封装类型有String,Number,Boolean
当读取字符串、数字或布尔值时,原始封装类型将被自动创建。
var name = "cxf";
var firstChar = name.charAt(0);
console.log(firstChar);
背后JavaScript引擎(engine):
var name = "cxf";
var temp = new String(name); // 自动打包。
var firstChar = temp .charAt(0);
temp = null;
console.log(firstChar);
var name = "cxf";
name.last = "Beth";
console.log(name.last); // undefined
背后JavaScript引擎(engine):
var name = "cxf";
var temp = new String(name);
temp.last = "Beth";
temp = null;
var temp = new String(name);
console.log(temp.last);
temp = null;
临时对象仅在值被读取时创建。
var name = "cxf";
var count = 12;
var found = false;
console.log(name instanceof String); // false
console.log(count instanceof Number); // false
console.log(found instanceof Boolean); // false
instanceof操作符并没有真的读取任何东西。
手动创建原始封装类型,会创建一个object,这意味着typeof无法鉴别实际保存的数据的类型。
var name = new String("cxf");
var count = new Number(12);
var found = new Boolean(false);
console.log(typeof name); // object
console.log(typeof count); // object
console.log(typeof found); // object
var found = new Boolean(false);
if(found) {
console.log("Found");
} // 即使是false,也总是被执行。因为一个对象在条件判断语句中总被认为是true
var found = false;
if(found) {
console.log("Found");
} else {
console.log("Not found");
} // Not found
var temp = /[?&][^?&]+=[^?&]+/g;
console.log(typeof temp); // object,正则表达式返回object。
函数
函数其实就是对象,使函数不同于其他对象的决定性特点是函数存在一个被称为[[Call]]的内部属性(函数独有的[[Call]]属性表明该对象可以被执行,[[Call]]该内部属性包含了该函数的执行指令)。ECMAScript定义typeof操作符会在对象内查找这个内部属性,对任何具有[[Call]]属性的对象返回“function"。
内部属性无法通过代码访问,而是定义了代码执行时的行为。
内部属性都用双重中括号来标注。
定义函数:(1)通过函数表达式(2)通过函数声明(3)通过Function构造函数
函数表达式可以是匿名函数或具名函数表达式(名字只能在内部被访问,例如递归),取而代之通常会被一个变量或属性引用,将一个函数作为值赋值给变量,最后多了个分号。
在函数的真实形式直到运行时才能确定时不得不用Function构造函数。
var add = new Function('x', 'y', 'return x+y'); // 把代码放在字符串里(对于工具是不可访问的)
重要区别就是:函数声明会被提升至上下文(要么是 该函数被声明时所在的函数的范围,要么是 全局范围)的顶部。意味着可以先使用函数后声明它们。
(因为JavaScript引擎会将函数声明放在其作用域最前面,提前知道了函数的名字)
函数声明是做了完全(整体)提升,变量声明是部分提升(只对于声明有效,赋值过程无效)。
function f10 { } 而 者 名 函 数 表 达 式 的 name 则 是 一 个 空 字 符 串 : > var f2 = function 0 { } ; 具 名 函 数 表 达 式 也 有 一 个 name : > var f3 = function myName() 0 ; 函 数 的 名 称 对 于 debug 是 非 常 有 用 的 。 正 因 如 此 , 有 一 些 开 发 者 往 往 会 给 函 数 表 达 式 加 上 名 字 。 " v:shapes="图片_x0020_213">
所有的函数都是对象、Function构造器的实例:
function id(x) {
return x;
}
console.log(id instanceof Function); // true
var numbers = [1,5,6,8,2,7,10];
numbers.sort();
console.log(numbers); // [ 1, 10, 2, 5, 6, 7, 8 ];
因为默认情况下,sort()将数组中每个对象转换成字符串,然后进行比较。
numbers.sort(function(first,second) {
return first - second;
});
console.log(numbers); // [ 1, 2, 5, 6, 7, 8, 10 ];
数组的sort()方法接受一个比较函数作为可选参数。传递给sort()的比较函数是一个函数表达式。第一个数小于第二个时返回负数。相等时返回0。
只要记住函数就是对象,很多行为都变得容易理解。
JavaScript函数的另一个独特之处,在于可以给函数传递任意数量的参数却不造成错误。那是因为,函数参数实际上被保存在一个被称为arguments的类似数组的对象中。如同一个普通的JavaScript数组,arguments可以自由增长,值可通过数字索引来引用。arguments的length属性会告诉你目前有多少个值。
arguments对象自动存在于函数中。也就是说,函数的命名参数不过是为了方便,并不真的限制该函数可接受函数的个数。
注意:arguments对象不是一个数组的实例,其拥有的方法与数组不同,Array.isArray(arguments)永远返回false。
function reflect(value) {
console.log(Array.isArray(arguments)); // false
}
reflect();
length属性表明了该函数的期望参数个数。
注意实际传入的参数的数量不影响函数的期望参数个数。
function reflect(value) {
return value;
}
console.log(reflect("cxf",111)); // cxf
console.log(reflect.length); // 1 不变
reflect = function() {
return arguments[0];
}
console.log(reflect("cxf",111)); // cxf
console.log(reflect.length); // 0 不变
如果两个放一起运行,第一个也是0。
arguments
可选参数(设默认值):
例子:求和
function sum() {
var result = 0, i = 0, len = arguments.length; // 会变
while(i < len) {
result += arguments[i];
i++;
}
return result;
}
console.log(sum(1,1)); // 2
console.log(sum()); // 0
console.log(sum(8)); // 8
console.log(sum(4+6+9+1));
p-arseInt('2', 1 ) 总 之 , 当 你 不 明 确 函 数 或 者 方 法 的 调 用 方 式 时 , 你 需 要 格 外 注 意 。 一 旦 你 要 使 用 这 些 函 数 , 你 就 要 格 外 明 确 函 数 接 受 哪 些 参 数 , 同 时你会传入哪些参数@ 这 是 我 们 通 过 回 调 来 实 现 的 方 式 · 歹 l.map(function ( { return parselnt(). 茈 ) } ) " v:shapes="图片_x0020_207">
变量的作用域是指变量在何处可以被访问到。
以前只有函数级作用域,ES6后有块级作用域了(块就是指{}包围的范围)。
function { 、 不 e t 「 . C strictFunc() ReferenceError: X 飞 、 not 竺 123 〕 " v:shapes="图片_x0020_205">
IIFE改造:
全局对象
getAllPropertyNames(window) . SO 「 t() .sltce(), 5 ) [ •AnalyserNode', •Array', •ArrayBuffer•, 'Attr', 'Audio' 〕 JavaScript 之 父 BrendanEich 认 为 全 局 对 象 的 设 计 是 他 “ 最 大 的 遗 憾 六 它 影 响 了 性 能 , 使 得 变 量 的 作 用 域 的 实 现 变 得 更 为 复 杂 , 并 且 导 致 模 块 化 代 码 的 减 少 。 16 . 8 , 1 跨 平 台 兼 容 浏 览 器 和 Node.js 都 有 一 些 全 局 的 变 量 可 以 引 用 全 局 的 对 象 。 不 幸 的 是 , 它 们 是 不 一 样 的 : 。 浏 览 器 中 的 全 局 对 象 是 丽 nd 。 w , 它 是 文 档 对 象 模 型 (DOM) 的 一 部 分 , 而 非 ECMAScnpt 5 的 一 部 分 。 在 每 一 个 帧 或 者 window 中 , 都 有 一 个 全 局 对 象 。 Node.js 中 的 全 局 对 象 是 global , 它 是 一 个 Node.js 专 属 的 变 量 。 每 一 个 模 块 都 有 它 自 己 的 作 用 域 , 在 这 些 作 用 域 中 this 指 向 了 这 个 作 用 域 的 对 象 。 因 此 , 乜 h 和 global 在 模 块 中 是 不 同 的 。 在 两 个 平 台 上 , this 都 指 向 全 局 对 象 , 但 是 这 仅 仅 是 在 全 局 作 用 域 中 。 而 这 在 Node.js 中 是 不 可 能 的 。 如 果 你 想 用 一 种 跨 平 台 的 方 式 来 访 问 全 局 对 象 , 你 可 以 像 下 面 这 样 做 : (function ( 醮 0b ) { / / glob PO 亡 5 to global 0b 丿 'undefined , ? window : global) ) ; )(typeof Hindow ! = = " v:shapes="图片_x0020_198">
function sayMessage(message) {
console.log(message);
}
function sayMessage() {
console.log("Default message");
}
sayMessage("Hello"); // Default message
同名函数,只有最后定义的有效,之前的函数声明被完全删除。
用对象来帮助理解:
var sayMessage = new Function("message","console.log(message);");
sayMessage = new Function("console.log(\"Default message\");")
sayMessage("Hello"); // sayMessage连续赋了两次函数对象,第一个自然丢失了。
可以用arguments对象获取传入的参数个数并决定怎么处理。
即:
if (arguments.length === 0) {
message = "Default message";
}
console.log(message);
注意:在实际使用中,检查命名参数是否为未定义比依靠arguments.length更常见。
如果属性的值是函数,则该属性被称为方法。
可以像添加属性那样给对象添加方法。
var person = {
name: "cxf",
sayName: function() {
console.log(this.name); // 不要用person,改变变量名就必须改变方法里引用的名字,这种紧耦合不好,所以要用this。
}
};
person.sayName(); // cxf
所有函数作用域内都有一个this对象代表调用该函数的对象。
在全局作用域中,this代表全局对象(浏览器里的window)。
当一个函数作为对象的方法被调用时,默认this的值等于那个对象。
this可避免紧耦合,要是改person,就老是得改对应引用的话,会很麻烦。
function sayNameForAll() {
console.log(this.name);
}
var person1 = {
name: "cxf",
sayName: sayNameForAll
};
var person2 = {
name: "Beth",
sayName: sayNameForAll
};
var name = "Tone";
person1.sayName(); // cxf
person2.sayName(); // Beth
sayNameForAll(); // undefined; 为什么?
this在函数调用时才被设置。
改变this:
call()
apply()
bind()
改变属性特征,可使用Object.defineProperty(拥有该属性的对象,"属性名", )
整数和浮点数(国际标准 IEEE 754)
JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。所以,1与1.0是相同的,是同一个数。
由于浮点数不是精确的值,所以涉及小数的比较、运算要特别小心。
最佳实践是不要直接比较非整数
取而代之,将边界错误的上界(机器精度)考虑进来,对于双精度一个标准的精度值是2的-53次方:
%是求余,不是取模,因为它会返回与第一个操作数符号相同的值。
+number 保持参数不变;非数字会被转换成数字
特殊的数字值:
- 1. 两个错误值:NaN 和 Infinity
- 2. 两个零值:+0 和 -0(一个数字的正负号和数值是分开存储的)
NaN:
- 1. NaN是唯一一个和自身不相等的值
Array.prototype.indexOf也使用了严格相等(===),因此不能通过该方法在数组中查找NaN
如果要检查一个值是否是NaN,必须使用全局函数isNaN()
对非数字不起作用,因为它首先做的是把值转换成数字,转换可能生成NaN,然后函数会错误地返回true
因此,最好的检验NaN的方法是将isNaN和typeof类型检查组合起来:
或者,利用NaN是唯一一个与自身不相等的特点,来检验NaN:
- 2. NaN("Not a Number")是一个数字
- 3. 一个不能被解析的数字
Number( 'xyz') UaN > Number (undefined) UaN " v:shapes="图片_x0020_184">
对比:
- 4. 失败的操作
Math acos (2) UaN > Math. log(-l) UaN > Math. sqrt(-l) UaN " v:shapes="图片_x0020_182">
- 5. 一个运算数是NaN(这样可以确保,如果在一个较长的运算中发生了错误,可以在最后结果中看到)
25 / NEN " v:shapes="图片_x0020_181">
Infinity
两种错误:大到无法表示的数字;或者除以0
(1)Infinity比任何数(除了NaN)大,-Infinity比任何数(除了NaN)小,所以需要最大值或最小值时可以当默认值
-Infinity>426332222222222222222 false > -Infinity<3 true " v:shapes="图片_x0020_180">
都是false
Nan false -Infinity < NON false Infinity < Nau false -Infinity > Nan false " v:shapes="图片_x0020_179">
(2)巨大的数字
指数必须在-1023到1024之间(开区间)
Math. pow(2, 1Ø24) 1023) 8 .98846567431158±+307 " v:shapes="图片_x0020_177">
不知道为什么没有-Infinity:
Math. pow(2, -1023) 1.1125369292536ae7e-308 > Math. pow(2, -1024) s .562684646268003±- 309 > Math. pow(2, -1025) 2 .781342323134±-309 " v:shapes="图片_x0020_176">
(3)被0除
-Ile -Infinity " v:shapes="图片_x0020_175">
对比:
(4)Infinity的运算
如果尝试用一个Infinity“抵消”另一个Infinity的时候,会得到错误的结果NaN:
Infinity - Infinity > Infinity / Infinity UaN " v:shapes="图片_x0020_172">
如果试图得到大于Infinity的书,得到的仍然是Infinity:
Infinity + Infinity Inf nity > Infinity * Infinity Infinity " v:shapes="图片_x0020_171">
(5)检查Infinity
严格相等和宽松相等都适用于Infinity:
附:全局函数isFinite()可以检查一个值是否是实际的值(既不是Infinity也不是NaN):
( -a) . toString() > (+0) . toString() > e. toString() O Uncaught SyntaxError: Invalid or unexpected token " v:shapes="图片_x0020_163">
6..toString(2) “110“" v:shapes="图片_x0020_162">
遵从IEEE754双精度浮点数标准,在js中我们通常写0,这意味着+0,但是它也意味着是-0
要记住和“.”点操作符区分开,要不然容易报错。为了区分有时要用两个"."
+0和-0大部分时候是一样的,都是0,但是也可以区分两个0:
除以两个0
判断两个0不同的权威方法是除以0:
还有其他可以区别的:
Math.pow()
Math.atan2()
string常用方法
//concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串。
var str = "Hello";
var out = str.concat(" World","!");
console.log(str); //Hello
console.log(out); //Hello World!
//charAt() – 返回指定位置的字符。
var str = "HelloString";
var out = str.charAt(1);
console.log(out); //e
//charCodeAt() – 返回在指定的位置的字符的 Unicode 编码。
var str = "HelloString";
var out = str.charCodeAt(5);
console.log(out); //83
//indexOf(searchvalue,fromindex) – 返回字符串中一个子串第一处出现的索引,如果没有匹配项,返回 -1 。
//fromindex是可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。
//如省略该参数,则将从字符串的首字符开始检索,此时indexOf()跟search()方法类似。
var str = "HelloStringend";
console.log(str.indexOf("e")); //1
console.log(str.indexOf("e",2)); //11
//lastIndexOf(searchvalue,fromindex) – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。
//如果在 stringObject 中的 fromindex 位置之前存在 searchvalue,则返回的是出现的最后一个 searchvalue 的位置。
var str = "HelloString";
console.log(str.lastIndexOf("l")); //3
console.log(str.lastIndexOf("l", 1)); //-1
console.log(str.lastIndexOf("l", 2)); //2
console.log(str.lastIndexOf("l", 3)); //3
//substring(start,end) – 返回一个新的字符串,包括 start 处的字符,但不包括 end 处的字符,其长度为 end 减 start
//substring是以两个参数中较小一个作为起始位置,较大的参数作为结束位置。
//注意:如果参数是负数,substring则会将负参数都直接转换为0,如果仅有一个参数,则从start开始到末尾。
var str = "HelloExample";
console.log(str); //HelloExample
console.log(str.substring(1, 3)); //el
console.log(str.substring(3, 1)); //el
console.log(str.substring(2)); //lloExample
console.log(str.substring(-1)); //HelloExample
console.log(str.substring(-1, -3)); //空字符串
console.log(str.substring(-1, 5)); //Hello
//substr(start [,length]) – 返回一个新的字符串,从起始索引号提取字符串中指定数目的字符。
//如果仅有一个参数,则从start开始到末尾。
//当接收的参数是负数时,substr是将第一个参数与字符串长度相加后的结果作为第一个参数
var str = "HelloExample";
console.log(str); //HelloExample
console.log(str.substr(1, 3)); //ell
console.log(str.substr(2, -1)); //空字符串
console.log(str.substr(1)); //elloExample
console.log(str.substr(-4, 2)); //mp
console.log(str.substr(-3)); //ple
//stringObject.slice(start,end) 返回一个新的字符串,包括 start 处的字符,但不包括 end 处的字符,其长度为 end 减 start
//当接收的参数是负数时,slice会将它字符串的长度与对应的负数相加,结果作为参数。如果仅有一个参数,则从start开始到末尾。
var str = "HelloExample";
console.log(str); //HelloExample
console.log(str.slice(1, 3)); //el
console.log(str.slice(2)); //lloExmaple
console.log(str.slice(3, 1)); //空字符串
console.log(str.slice(-4, -1)); //mpl
console.log(str.slice(-4, 0)); //空字符串
console.log(str.slice(-1, -4)); //空字符串
console.log(str.slice(1, -4)); //elloExa
//toLowerCase() – 将整个字符串转成小写字母。
//toLowerCase() – 将整个字符串转成小写字母。
var str = "How Are you";
console.log(str.toLowerCase()); //how are you
console.log(str.toUpperCase()); //HOW ARE YOU
/***********************************************/
/********支持正则表达式的 String 对象的方法*****/
/***********split,match,replace,search**********/
/***********************************************/
//stringObject.split(separator,howmany),返回一个字符串数组。该数组是通过在 separator 指定的边界处将字符串 stringObject 分割成子串创建的。返回的数组中的字串不包括 separator 自身。
var str = "How are you doing today";
console.log(str.split(" ")); //["How", "are", "you", "doing", "today"]
console.log(str); //How are you doing today
console.log(str.split("")); //["H", "o", "w", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", "g", " ", "t", "o", "d", "a", "y"]
console.log(str.split("", 3)); //["H", "o", "w"]
console.log(str.split("a")); //["How ", "re you doing tod", "y"]
console.log(str.split("good")); //["How are you doing today"]
var str = "a_db-c(d+e";
console.log(str.split(/[^a-z]/i)); //["a", "db", "c", "d", "e"]
/** match(searchvalue) 或 match(regexp)检查一个字符串是否匹配一个正则表达式。返回存放匹配结果的数组。
match() 方法将检索字符串 stringObject,以找到一个或多个与 regexp 匹配的文本。这个方法的行为在很大程度上有赖于 regexp 是否具有标志 g。
如果 regexp 没有标志 g,那么 match() 方法就只能在 stringObject 中执行一次匹配。如果没有找到任何匹配的文本, match() 将返回 null。否则,它将返回一个数组,其中存放了与它找到的匹配文本有关的信息。该数组的第 0 个元素存放的是匹配文本,而其余的元素存放的是与正则表达式的子表达式匹配的文本。除了这些常规的数组元素之外,返回的数组还含有两个对象属性。index 属性声明的是匹配文本的起始字符在 stringObject 中的位置,input 属性声明的是对 stringObject 的引用。
如果 regexp 具有标志 g,则 match() 方法将执行全局检索,找到 stringObject 中的所有匹配子字符串。若没有找到任何匹配的子串,则返回 null。如果找到了一个或多个匹配子串,则返回一个数组。不过全局匹配返回的数组的内容与前者大不相同,它的数组元素中存放的是 stringObject 中所有的匹配子串,而且也没有 index 属性或 input 属性。
**/
var str = "Hello world! Hello";
console.log(str.match("lo")); //["lo"] { index: 3, input: "Hello world! Hello" }
console.log(str.match("world")); //["world"] { index: 6, input: "Hello world! Hello" }
console.log(str.match("world").index); //6
console.log(str.match(/Hello/g)); //["Hello", "Hello"]
console.log(str.match("World")); //null
var str = "1 plus 2 equal 3";
console.log(str.match(/\d+/g)); //["1", "2", "3"]
//replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
//stringObject.replace(regexp/substr,replacement),返回一个新的字符串,是用 replacement 替换了 regexp 的第一次匹配或所有匹配之后得到的。
//replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。但是 replacement 中的 $ 字符具有特定的含义,它说明从模式匹配得到的字符串将用于替换。
// $1、$2、...、$99----与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
// $&------------------与 regexp 相匹配的子串。
// $`------------------位于匹配子串左侧的文本。
// $'------------------位于匹配子串右侧的文本。
// $$------------------直接量符号。
var str = "Visit HangZhou";
console.log(str); //Visit HangZhou
console.log(str.replace(/Hang/g, "Su")); //Visit SuZhou
var str = "1 plus 2 equal 3";
console.log(str); //1 plus 2 equal 3
console.log(str.replace(/(\d)/g, "*")); //* plus * equal *
var str = "as An angle";
console.log(str.replace(/a/, "b")); //bs An angle
console.log(str.replace(/a/g, "b")); //bs An bngle
console.log(str.replace(/a/gi, "b")); //bs bn angle
var str = "Karl,John";
console.log(str.replace(/(\w+)\s*,\s*(\w+)/, "$2,$1")); //John,Karl
var str = '"ab", "b"';
console.log(str.replace(/"([^"]*)"/g, "'$1'")); //'ab', 'b'
var str = "aaa bbb ccc";
console.log(str.replace(/\b\w+\b/g, function (w) {
return w.substring(0, 1).toUpperCase() + w.substring(1);
})); //Aaa Bbb Ccc
//search() – 执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。
//stringObject.search(regexp) 返回stringObject 中第一个与 regexp 相匹配的子串的起始位置。
//此方法跟indexOf类似。此方法会忽略g标识
var str = "Visit HangZhou";
console.log(str) //Visit HangZhou
console.log(str.search(/Hang/)); //6
console.log(str.search(/hang/)); //-1
console.log(str.search(/hang/i)); //6
var str = "1 plus 2 equal 3";
console.log(str) //1 plus 2 equal 3
console.log(str.search(/\d/g)); //0
Array
数组字面量
数组最后的逗号(trailing comma)会被忽略
索引访问和length属性
arr[arr.length] = 'cxf'; // append an element 添加一个元素
arr.push('cxf'); // 另一种添加元素的方法
常用方法
Array对象常用方法中:
不改变原数组:
1、 concat()
连接两个或多个数组
不改变原数组
返回被连接数组的一个副本
2、join()
把数组中所有元素放入一个字符串
不改变原数组
返回字符串
3、 slice()
从已有的数组中返回选定的元素
不改变原数组
返回一个新数组
4、 toString()
把数组转为字符串
不改变原数组
返回数组的字符串形式
改变原数组(破坏性):
5、 pop()
删除数组最后一个元素,如果数组为空,则不改变数组,返回undefined
改变原数组
返回被删除的元素
6、 push()
向数组末尾添加一个或多个元素
改变原数组
返回新数组的长度
7、 reverse()
颠倒数组中元素的顺序
改变原数组
返回该数组
8、 shift()
把数组的第一个元素删除,若空数组,不进行任何操作,返回undefined
改变原数组
返回第一个元素的值
9、 sort()
对数组元素进行排序(ascii)
改变原数组
返回该数组
10、 splice()
从数组中添加/删除项目
改变原数组
返回被删除的元素
11、 unshift()
向数组的开头添加一个或多个元素
改变原数组
返回新数组的长度
indexOf
sort
forEach
every
some
映射函数map和归约函数reduce
map转化方法接收一个输入数组,输出一个数组。所谓映射,是指它可以遍历数组,并且将函数应用于每个元素(比如forEach)。但是他不是丢弃函数返回值,而是利用这些返回值重新建立一个新的数组。
reduce()即归约函数(reduce or fold折叠)通过重复调用一个函数//(该函数将数组的每个元素都加到一个基值上),将数组转化为单一值。
forEach在一些类库的实现是.each
this
用div[i]得用闭包传参。
alert出100
构造函数:
new test后,实例化了一个对象,this就是指向这个test对象,不是指向window了,
所以类似生活中的案例,直接指明(不推荐)
推荐:
闭包
什么是闭包?
在我的理解里,就是嵌套的函数,且外部函数返回内部函数,即能够读取其他函数内部变量的函数。在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
下面就是典型的例子:
function outerf() {
var a = 5;
function innerf() {
a++;
alert(a);
}
return innerf;
}
var f = outerf();
f(); // 6
f(); // 7
也可以写成下面这种形式(即内部函数是匿名函数):
function outerf() {
var a = 5;
return function() {
a++;
alert(a);
}
}
var f = outerf();
f(); // 6
f(); // 7
另外还可以这样:
而普通函数是:
function f() {
var a = 5;
a++;
alert(a);
}
f(); // 6
f(); // 6
每次执行f()后a变量都会被回收。
我们都知道,内部函数可以引用外部函数的参数和变量。相反则不能。
function f() {
var a = 1;
}
alert(a); // a is not defined
普通函数一旦被执行,它的参数和变量就会被JS中的垃圾回收机制回收;但使用闭包时,即使外部函数被执行了,内部函数的引用还在,所以参数和变量还是在内存里。
闭包有什么好处/优点?有哪些应用/用途?
(允许函数访问局部作用域之外的数据)
好处:
- 变量长期储存在内存里。
- 避免全局变量的污染。
- 模拟私有成员/私有方法
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
或写成下面这种形式:
用法:
- 模块化代码
- 可以读取函数内部的变量
- 让这些变量的值始终保持在内存中
eg: 在循环中直接找到对应元素的索引
如果是下面这样写,都是同一个数,也就是ALi.length。(只有点击才会触发,然后循环已经结束)
<ul>
<li> index = 0 </li>
<li> index = 1 </li>
<li> index = 2 </li>
<li> index = 3 </li>
</ul>
<script type="text/javascript">
var nodes = document.getElementsByTagName('li');
for(i = 0;i<nodes.length;i+=1) {
nodes[i].onclick = function() {
console.log(i+1); //不使用闭包的话,值每次都是4
}(4);
}
</script>
闭包的解决是:
会返回0,1 ,2……
也可以写成下面的形式:
一开始的典型例子可以变形为下面这样,也叫模块化代码:
var f = (function() {
var a = 5;
return function() {
a++;
alert(a);
}
})();
f(); // 6
f(); // 7
立即执行函数:加个括号变成表达式,然后加个括号执行。
(function() {
var a = 1;
alert(a);
})();
或者加个名字:
(function f() {
var a = 1;
alert(a);
})();
注意下面的波浪线区别:
闭包需要注意的地方有哪些?
- 闭包在IE中会引发内存泄露(由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。)
解决方法类似这样:
或者:
- 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。(这句话不理解)
理解巩固:
例子1:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()()); // My Object
例子2:
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); // The Window 函数中的this一般是指向window中的变量。即this的指向是由它所在函数调用的上下文决定的,而不是由它所在函数定义的上下文决定的。
如果非要指向object,还可以把代码的最后一句改为 alert(object.getName().call(object));
严格模式
"use strict"
针对脚本文件,将"use strict"放在脚本第一行,则整个脚本都将以“严格模式”运行,不在第一行则无效,以“普通模式”运行;(不利于文件合并)
针对单个函数,将"use strict"放在函数体第一行,则整个函数都将以“严格模式”运行。
将整个脚本文件放在一个立即执行的匿名函数中最好。
(
function() {
"use strict";
}
)();
区别:
严格模式:
变量必须通过var进行声明,否则将会报错。
示例:
"use strict";
x = 1;
console.log(x); // ReferenceError: x is not defined
"use strict";
for(var i=0;i<10;i++) {
console.log(i);
}
为了让代码更安全,禁止this关键字指向全局对象。
this从普通模式的window变成严格模式的undefined
示例:
eval("var a = 200; console.log(a);"); // 200
console.log(a); // 200
"use strict";
var fn = function() {
console.log(this); // undefined
}
fn();
所以,构造函数只要不通过new实例化对象,那么就会直接报错,因为undefined无法设置属性。
"use strict";
var Cat = function(name) {
this.name = name;
this.say = function() {
console.log(this.name);
}
};
Cat("咪咪");
window.say(); // Uncaught TypeError: Cannot set property 'name' of undefined
为了让代码更安全,禁止删除变量。
示例:
var x = 111;
delete x;
console.log(x); // SyntaxError: Delete of an unqualified identifier in strict mode.
"use strict";
var obj = {};
obj.y = 10;
delete obj.y;
console.log(obj.y); // undefined
普通模式下,如果对象有多个重名属性(重名函数可以用arguments[i]读取),最后赋值的那个属性会覆盖前面的值,严格模式下,这属于语法错误。
"use strict";
var obj = {
x: 200,
x: 300
};
console.log(obj);
都是300,为什么?
普通模式下,JS语言有两种变量作用域(scope):全局作用域和函数作用域;严格模式创设了第三种作用域:eval作用域。
严格模式下,eval语句本身就是一个作用域。它所生成的变量只能用于eval内部。
"use strict";
eval("var a = 200; console.log(a);");
console.log(a); // ReferenceError: a is not defined
var fn = function() {
eval("var x = 100");
console.log(x); // 100
}
fn();
"use strict";
var fn = function() {
eval("var x = 100");
console.log(x); // ReferenceError: x is not defined
}
fn();
arguments对象的限制
arguments是函数的参数对象,严格模式对它的使用做了限制
1、不运行对arguments赋值
2、arguments不再追踪参数的变化
3、禁止使用arguments.callee,这意味着,我们无法在匿名函数内部调用自身(递归)了
禁用with关键字
当代码执行到with语句时,执行环境的作用域链临时被改变。一个新的变量对象被创建,它包含了参数指定的对象的所有属性。这个对象被推入作用域链的首位,这意味着函数的所有局部变量处于第二个作用域链对象中,因此访问的代价变高了。
示例:
"use strict";
var obj = {};
obj.a = 1;
obj.b = 2;
with(obj) {
console.log(a + b); // SyntaxError: Strict mode code may not include a with statement
}
不允许使用关键字
为了向将来JavaScript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private, protected, public, static, yield
示例:
var extends = "我是extends";
console.log(extends);
报错:
SyntaxError: Unexpected token extends
// "use strict";
var interface = "我是interface";
console.log(interface); // 我是interface
"use strict";
var interface = "我是interface";
console.log(interface);
报错:
SyntaxError: Unexpected strict mode reserved word
为了让代码更安全,禁止在函数内部遍历调用栈
示例:
// "use strict";
var fn = function() {
console.log(arguments.length);
}
fn("abc","123"); // 2 两种模式都是2 为什么?
严格模式下,对禁止扩展的对象添加新属性,会报错。
示例:
"use strict";
var obj = {};
obj.x = 1;
Object.preventExtensions(obj);
obj.y = 2;
console.log(obj); // TypeError: Can't add property y, object is not extensible
普通模式下,不会报错,只会默默失败。
禁止八进制表示法
示例:
"use strict";
var obj = 0100; // 64
console.log(obj); // SyntaxError: Octal literals are not allowed in strict mode.
函数必须声明在顶层(现在好像可以了)
示例:
"use strict";
var a = 1;
if (a>0) {
(function() {
console.log("行");
})();
}
"use strict";
var a = 1;
if (a>0) {
function fn() {
console.log("不行");
}
fn();
}
setTimeout(函数,毫秒数)
编译是将代码转换成适合计算机的表示方式,通常可改善运行阶段性能。
一开始时是解释型->即时编译
标准语言定义
HTML(内容和结构)和css(样式)是声明型的,js是行为(计算)
document.getElementById('pox').style.color = 'red';
onclick="***()"
用[]而不是.可以使用有特殊符号的属性
结果是大桃花。
给Object加就都有了。
javascript有对象,没有类(但有构造函数)。
私有属性和封装:
JavaScript包括 ECMAScript, DOM, BOM
2 JavaScript 的 基 本 类 型 有 string, number, boolean,undefined,null
3 . JavaScript 的 复 合 类 型(对象类型) 有 Object,Array,Number, String, Boolean , Function,Argument,Date, RegExp, Math,Error。
(JavaScript的对象是键值对的集合)
4 . JavaScript 还 有 两 个 空 类 型 : undefined 和 null
5 . JavaScript 中 获 得 类 型 的 运 算 符 是 typeof, 使 用 该 运 算 符 返 回 什 么 数 据 类 型 ? string
6 . JavaScript 中 = = = 和 = = 有 什 么 区 别 ? 全等是既比较值,又比较类型。
7 . JavaScript 中 in 运 算 符 有 什 么 用 ? 判断一个对象是否具有某一个属性。还有for ( var i in object )用法。
& JavaScript 的 条 件 运 算 符 是
9 . JavaScript 中 创 建 对 象 使 用 运 算 符
例子:(副本与快捷方式的区别)
10 . JavaScript 什 么 叫 逻 辑 中 断 :
浏览器可直接设断点,刷新,点击箭头或F11执行下一步,VM是内部提供的虚拟机,F10跳过,watch或鼠标放变量上或直接出来(新浏览器)等。
可以直接if (num)也可以直接三元运算符,更好更简单的方法是逻辑(短路)||:
1 1 . JavaScript 中 delete 运 算 符 的 作 用 是
false true 1 m is not defined " v:shapes="图片_x0020_78">
arr[2]的位置是undefined,arr.length还是4
12 . JavaScript 中 循 环 语 旬 有 种 . 分 别 是 .
13 . JavaScript 中 分 支 语 句 有种 、 分 别 是 :
1 生 JavaScripv 中 跳 转 语 句 break 与 continuega 何 使 用 ?
和
有等号是表达式。例如a = 100 例如
加分号不是表达式,是语句。
for while do-while for-in
if-else switch
break跳出循环 continue跳出本次循环
JSON
JSON,全称是 JavaScript Object Notation,即 JavaScript 对象标记法。
JSON 是一种轻量级(Light-Weight)、基于文本的(Text-Based)、可读的(Human-Readable)格式。
JSON 的名称中虽然带有 JavaScript,但这是指其语法规则是参考 JavaScript 对象的,而不是指只能用于 JavaScript 语言。
JSON 无论对于人,还是对于机器来说,都是十分便于阅读和书写的,而且相比 XML (另一种常见的数据交换格式),文件更小,因此迅速成为网络上十分流行的交换格式。
近年来 JavaScript 已经成为浏览器上事实上的标准语言,JavaScript 的风靡,与 JSON 的流行也有密切的关系。
因为 JSON 本身就是参考 JavaScript 对象的规则定义的,其语法与 JavaScript 定义对象的语法几乎完全相同。
JSON 格式的创始人声称此格式永远不升级,这就表示这种格式具有长时间的稳定性,10 年前写的文件,10 年后也能用,没有任何兼容性问题。
2. JSON 的语法规则是怎样的
JSON 的语法规则十分简单,可称得上“优雅完美”,总结起来有:
- 数组(Array)用方括号(“[]”)表示。
- 对象(Object)用大括号(”{}”)表示。
- 名称/值对(name/value)组合成数组和对象。
- 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
- 并列的数据之间用逗号(“,”)分隔
{
"name": "Geoff Lui",
"age": 26
}
3. JSON 和 XML
JSON 常被拿来与 XML 做比较,因为 JSON 的诞生本来就多多少少要有取代 XML 的意思。相比 XML,JSON 的优势如下:
- 没有结束标签,长度更短,读写更快
- 能够直接被 JavaScript 解释器解析
- 可以使用数组
JSON:
{
"name": "Geoff Lui",
"age": 26,
"friends": ["Lily", "Lucy", "Gwen"]
}
XML:
<root>
<name>Geoff Lui</name>
<age>26</age>
<friends>Lily</friends>
<friends>Lucy</friends>
<friends>Gwen</friends>
</root>
4. JSON 解析和生成
在 JavaScript 中,有两个方法与此相关: JSON.parse 和 JSON.stringify 。
语法
上一课提到的 JSON 的五点语法:
- 数组(Array)用方括号(“[]”)表示。
- 对象(Object)用大括号(”{}”)表示。
- 名称/值对(name/value)之间用冒号(”:”)隔开。
- 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
- 并列的数据之间用逗号(“,”)分隔
1. 对象(Object)
对象用大括号(“{}”)括起来,大括号里是一系列的“名称/值对”,请看概念图。
两个并列的数据之间用逗号(“,”)隔开,注意两点:
- 使用英文的逗号(“,”),不要用中文的逗号(“,”)
- 最后一个“名称/值对“之后不要加逗号
2. 数组(Array)
数组表示一系列有序的值,用方括号(“[]”)包围起来,并列的值之间用逗号分隔,请看概念图。
例如,以下的数组是合法的:
3. 名称/值对(Name/Value)
名称(Name)是一个字符串,要用双引号括起来,不能用单引号,也不能没有引号,这一点与 JavaScript 不同。
值的类型只有七种:字符串(string)、数值(number)、对象(object)、数组(array)、true、false、null。不能有这之外的类型,例如 undefined、函数等。请看概念图。
字符串(string)的规则如下:
- 英文双引号括起来,不能用单引号,也不能没有。
- 字符串中不能单独出现双引号(”) 和右斜杠(“\”)。
- 如果要打双引号或右斜杠,需要使用“右斜杠+字符”的形式,例如 \” 和 \\,其它的转义字符也是如此
字符串的概念图。
数值的概念图。
字符串转化为对象parse()
解析,是指将符合 JSON 语法规则的字符串转换成对象的过程。
不同的编程语言都提供了解析 JSON 字符串的方法,在这里主要讲解 JavaScript 中的解析方法。主要有三种:
- 使用 eval()
- 使用 JSON.parse()
- 使用第三方库,例如 JQuery 等
1. eval()
eval() 函数的参数是一个字符串,其作用是直接执行其中的 JavaScript 代码。
eval() 能够解析 JSON 字符串。从这里也可以看得出,JSON 和 JavaScript 是高度嵌合的。
但是,现在已经很少直接使用 eval() 来解析了,如果您的浏览器版本真的是很旧,可能才需要这个方法。此外,eval() 是一个相对危险的函数,因为字符串中可能含有未知因素。在这里,作为学习,还是要知道这也是一种方法。
请注意 eval() 的参数,在字符串两旁加了括号,这是必须的,否则会报错。
因为 JSON 字符串是被大括号(“{}”)包围的,直接放到 eval() 会被当成语句块来执行,因此要在两旁加上括号,使其变成表达式。
2. JSON.parse()
现在绝大多数浏览器都以支持 JSON.parse(),是推荐使用的方式。
如果输入了不符合规范的字符串,会报错。
JSON.parse() 可以有第二个参数,是一个函数。此函数有两个参数:name 和 value,分别代表名称和值。当传入一个 JSON 字符串后,JSON 的每一组名称/值对都要调用此函数。该函数有返回值,返回值将赋值给当前的名称(name)。
利用第二个参数,可以在解析 JSON 字符串的同时对数据进行一些处理。
对象转化为字符串stringify()
序列化,指将 JavaScript 值转化为 JSON 字符串的过程。
JSON.stringify() 能够将 JavaScript 值转换成 JSON 字符串。JSON.stringify() 生成的字符串可以用 JSON.parse() 再还原成 JavaScript 值。
1. 参数的含义
JSON.stringify(value[, replacer[, space]])
value:必选参数。被变换的 JavaScript 值,一般是对象或数组。
replacer:可以省略。有两种选择:函数或数组。
- 如果是函数,则每一组名称/值对都会调用此函数,该函数返回一个值,作为名称的值变换到结果字符串中,如果返回 undefined,则该成员被忽略。
- 如果是数组,则只有数组中存在名称才能够被转换,且转换后顺序与数组中的值保持一致。
space:可以省略。这是为了排版、方便阅读而存在的。可以在 JSON 字符串中添加空白或制表符等。
2. value 用法
3. replacer 的用法
4. space 的用法
JSON和XML的转换
1. 下载相关文件
- JQuery
- jquery.json2xml.js
- jquery.xml2json.js
2. XML 字符串转换成 JSON 对象
$.xml2json(str);
3. JSON 对象转换成 XML 字符串
$.json2xml(obj);
Ajax和JSON
JSON 文件被放置在服务器端,客户端请求该文件用得最多的是 Ajax,能够实现异步请求。
1. Ajax 是什么
AJAX,全称 Asynchronous JavaScript and XML,即“异步的 JavaScript 和 XML”,一般写作 Ajax。
Ajax 能够与服务器交换少量数据,从而异步地更新部分网页。
异步,指的是当 Ajax 执行交换数据的操作时,其他的操作仍然可以执行。
一个最常见的应用是:打开百度或谷歌首页,当输入文字后,搜索栏下方会显示出几个建议的搜索词。这正是 Ajax 的应用。
2. 创建和使用 Ajax
创建 Ajax 对象要考虑浏览器的版本问题,主要分为两大类:IE7+/Chrome/Firefox/… 和 IE6/IE5.。
function CreateXHR(){
if (window.XMLHttpRequest)
{
//对浏览器 IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
else
{
//对浏览器 IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
然后,只要用如下方式创建即可。
var xmlhttp;
xmlhttp = CreateXHR();
服务器端有一个文件 test.json,请求并输出。
xmlhttp.open("GET","test.json",true);
xmlhttp.send();
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
var jsonstr = xmlhttp.responseText;
console.log(jsonstr);
}
}
其中,xmlhttp.readyState 存有 XMLHttpRequest 的状态,有五个值:
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
xmlhttp.status 的值为请求结果,200 表示“OK”,404 表示未找到页面。
获取来自服务器的响应,可使用 XMLHttpRequest 对象的 responseText 或 responseXML 属性,前者是以字符串形式,后者是以 XML 形式。
跨源资源共享
标 签 。 我 们 知 道 , 一 个 网 页 可 以 从 任 何 网 页 中 加 载 图 像 , 不 用 担 心 跨 域 不 跨 域 。 这 也 是 在 线 广 告 齦 踪 浏 览 量 的 主 要 方 式 。 正 如 第 13 章 讨 论 过 的 , 也 可 以 动 态 地 创 建 图 像 . 使 用 它 们 的 onioad 和 oncrrcr 事 件 处 理 程 序 来 确 定 是 否 接 收 到 了 响 应 到 动 态 创 建 图 像 经 常 用 于 图 像 Pingo 图 像 Ping 是 与 服 务 器 进 行 简 单 、 单 向 的 跨 域 通 信 的 一 种 方 式 到 请 求 的 数 据 是 通 过 查 询 字 符 串 形 式 发 送 的 . 而 响 应 可 以 是 任 意 内 容 . 但 通 常 是 像 素 或 2 偶 响 应 。 通 过 图 像 ping. 浏 览 器 得 不 到 任 何 具 体 的 数 据 , 但 通 过 侦 听 1 d 和 error 事 件 , 它 能 知 道 晌 应 是 什 么 时 候 接 收 到 的 。 凍 看 下 面 的 例 子 。 imq . 0010 d i , 0 , 0 《 alert 俨 ] ! 。 0 " v:shapes="图片_x0020_67">
Comet
术
SSE
JSONP
JSON with padding
元 素 ( 要 了 解 详 细 信 息 , 请 参 考 第 13 章 ) 来 使 用 的 , 使 用 时 可 以 为 src 属 跬 指 定 一 个 跨 域 URL 这 里 的 < 艹 p 元 素 与 元 素 类 似 , 都 有 能 力 不 受 限 制 地 从 其 他 域 加 载 资 源 。 因 为 JSONP 是 有 效 的 JavaScript 代 码 , 所 以 在 请 求 完 成 后 , 即 在 JSONP 响 应 加 载 到 页 而 中 以 后 , 就 会 立 即 执 行 。 来 看 一 个 例 了 。 function handleResponge (response) { 《 , You , re at 4 response . ip ' •. Which is in + response .region_name) ; “ 斗 var script , document .createE1ement( 咩 过 cr p 门 ; "http : / / freegeoip j 90n / ?caiIbackrhandLeRespOnse• script . StC document . body. insertBefore (script , d0010Pn 上 .body . firstchilä) : J 、 0 PE a 化 / 汤 这 个 例 子 通 过 查 询 地 理 定 位 服 务 来 显 示 你 的 IP 地 址 和 位 置 信 息 “ JSONP 之 所 以 在 开 发 人 员 中 极 为 流 行 , 主 要 原 因 是 它 非 常 简 单 易 用 。 与 图 像 Ping 相 比 , 它 的 优 点 在 于 能 够 直 接 访 问 响 应 文 本 , 支 持 在 浏 览 器 与 服 务 器 之 间 双 向 通 信 。 不 过 , JSONP 也 有 两 点 不 足 。 首 先 , JSONP 是 从 其 他 域 中 加 载 代 码 执 行 如 果 其 他 域 不 安 全 , 很 可 能 会 在 响 应 中 夹 带 一 些 恶 意 代 码 , 而 此 时 除 了 完 全 放 弃 JSONP 调 用 之 外 , 没 有 办 法 追 究 。 因 此 在 使 用 不 是 你 自 己 运 维 的 web 服 务 时 , 一 定 得 保 证 它 安 全 可 靠 。 其 次 , 要 确 定 JSONP 请 求 是 否 失 败 并 不 容 易 。 虽 然 HTML5 给 < scrip 。 元 素 新 增 了 一 个 onerror 事 件 处 理 程 序 , 但 目 还 没 有 得 到 任 何 浏 览 器 支 持 。 为 此 , 开 发 人 员 不 得 不 使 用 计 时 器 检 测 指 定 时 间 内 " v:shapes="图片_x0020_59">
提供了一种方式从另一个站点获取信息
用JSON来传数据,靠JSONP来跨域。
Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;
Web页面上调用js文件时则不受是否跨域的影响。不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);
JavaScript 正则表达式(Regular Expression,在代码中常简写为regex、regexp或RE)
正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。
这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法。
使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式。
搜索模式可用于文本搜索和文本替换。
两种形式的语法:
/pattern/flags(flags标志可选)
new RegExp(pattern [, flags])
正则表达式中的特殊字符
|
字符 |
含义 |
|
匹配将依照下列规则: 在非特殊字符之前的反斜杠表示下一个字符是特殊的,不能从字面上解释。例如,没有前面'\'的'b'通常匹配小写'b',无论它们出现在哪里。如果加了'\',这个字符变成了一个特殊意义的字符,意思是匹配一个字符边界。 反斜杠也可以将其后的特殊字符,转义为字面量。例如,模式 /a*/ 代表会匹配 0 个或者多个 a。相反,模式 /a\*/ 将 '*' 的特殊性移除,从而可以匹配像 "a*" 这样的字符串。 使用 new RegExp("pattern") 的时候不要忘记将 \ 进行转义,因为 \ 在字符串里面也是一个转义字符。 |
|
|
匹配输入的开始。如果多行标志被设置为true,那么也匹配换行符后紧跟的位置。 例如,/^A/ 并不会匹配 "an A" 中的 'A',但是会匹配 "An E" 中的 'A'。 当 '^' 作为第一个字符出现在一个字符集合模式时,它将会有不同的含义。补充字符集合 一节有详细介绍和示例。 |
|
|
匹配输入的结束。如果多行标示被设置为true,那么也匹配换行符前的位置。 例如,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。 |
|
|
匹配前一个表达式0次或多次。等价于 {0,}。 例如,/bo*/会匹配 "A ghost boooooed" 中的 'booooo' 和 "A bird warbled" 中的 'b',但是在 "A goat grunted" 中将不会匹配任何东西。 |
|
|
匹配前面一个表达式1次或者多次。等价于 {1,}。 例如,/a+/匹配了在 "candy" 中的 'a',和在 "caaaaaaandy" 中所有的 'a'。 |
|
|
匹配前面一个表达式0次或者1次。等价于 {0,1}。 例如,/e?le?/ 匹配 "angel" 中的 'el',和 "angle" 中的 'le' 以及"oslo' 中的'l'。 如果紧跟在任何量词 *、 +、? 或 {} 的后面,将会使量词变为非贪婪的(匹配尽量少的字符),和缺省使用的贪婪模式(匹配尽可能多的字符)正好相反。 例如,对 "123abc" 应用 /\d+/ 将会返回 "123",如果使用 /\d+?/,那么就只会匹配到 "1"。 还可以运用于先行断言,如本表的 x(?=y) 和 x(?!y) 条目中所述。 |
|
|
(小数点)匹配除换行符之外的任何单个字符。 例如,/.n/将会匹配 "nay, an apple is on the tree" 中的 'an' 和 'on',但是不会匹配 'nay'。 |
|
|
匹配 'x' 并且记住匹配项,就像下面的例子展示的那样。括号被称为 捕获括号。 模式/(foo) (bar) \1 \2/中的 '(foo)' 和 '(bar)' 匹配并记住字符串 "foo bar foo bar" 中前两个单词。模式中的 \1 和 \2 匹配字符串的后两个单词。注意 \1、\2、\n 是用在正则表达式的匹配环节。在正则表达式的替换环节,则要使用像 $1、$2、$n 这样的语法,例如,'bar foo'.replace( /(...) (...)/, '$2 $1' )。 |
|
|
匹配 'x' 但是不记住匹配项。这种叫作非捕获括号,使得你能够定义为与正则表达式运算符一起使用的子表达式。来看示例表达式 /(?:foo){1,2}/。如果表达式是 /foo{1,2}/,{1,2}将只对 ‘foo’ 的最后一个字符 ’o‘ 生效。如果使用非捕获括号,则{1,2}会匹配整个 ‘foo’ 单词。 |
|
|
匹配'x'仅仅当'x'后面跟着'y'.这种叫做正向肯定查找。 例如,/Jack(?=Sprat)/会匹配到'Jack'仅仅当它后面跟着'Sprat'。/Jack(?=Sprat|Frost)/匹配‘Jack’仅仅当它后面跟着'Sprat'或者是‘Frost’。但是‘Sprat’和‘Frost’都不是匹配结果的一部分。 |
|
|
匹配'x'仅仅当'x'后面不跟着'y',这个叫做正向否定查找。 例如,/\d+(?!\.)/匹配一个数字仅仅当这个数字后面没有跟小数点的时候。正则表达式/\d+(?!\.)/.exec("3.141")匹配‘141’但是不是‘3.141’ |
|
|
匹配‘x’或者‘y’。 例如,/green|red/匹配“green apple”中的‘green’和“red apple”中的‘red’ |
|
|
n是一个正整数,匹配了前面一个字符刚好发生了n次。 比如,/a{2}/不会匹配“candy”中的'a',但是会匹配“caandy”中所有的a,以及“caaandy”中的前两个'a'。 |
|
|
n 和 m 都是整数。匹配前面的字符至少n次,最多m次。如果 n 或者 m 的值是0, 这个值被忽略。 例如,/a{1, 3}/ 并不匹配“cndy”中的任意字符,匹配“candy”中得a,匹配“caandy”中的前两个a,也匹配“caaaaaaandy”中的前三个a。注意,当匹配”caaaaaaandy“时,匹配的值是“aaa”,即使原始的字符串中有更多的a。 |
|
|
一个字符集合。匹配方括号的中任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。对于点(.)和星号(*)这样的特殊符号在一个字符集中没有特殊的意义。他们不必进行转义,不过转义也是起作用的。 例如,[abcd] 和[a-d]是一样的。他们都匹配"brisket"中得‘b’,也都匹配“city”中的‘c’。/[a-z.]+/ 和/[\w.]+/都匹配“test.i.ng”中得所有字符。 |
|
|
一个反向字符集。也就是说, 它匹配任何没有包含在方括号中的字符。你可以使用破折号(-)来指定一个字符范围。任何普通字符在这里都是起作用的。 例如,[^abc] 和 [^a-c] 是一样的。他们匹配"brisket"中得‘r’,也匹配“chop”中的‘h’。 |
|
|
匹配一个退格(U+0008)。(不要和\b混淆了。) |
|
|
匹配一个词的边界。一个词的边界就是一个词不被另外一个词跟随的位置或者不是另一个词汇字符前边的位置。注意,一个匹配的词的边界并不包含在匹配的内容中。换句话说,一个匹配的词的边界的内容的长度是0。(不要和[\b]混淆了) 例子: /\bm/匹配“moon”中得‘m’; /oo\b/并不匹配"moon"中得'oo',因为'oo'被一个词汇字符'n'紧跟着。 /oon\b/匹配"moon"中得'oon',因为'oon'是这个字符串的结束部分。这样他没有被一个词汇字符紧跟着。 /\w\b\w/将不能匹配任何字符串,因为一个单词中的字符永远也不可能被一个非词汇字符和一个词汇字符同时紧跟着。 注意: JavaScript的正则表达式引擎将特定的字符集定义为“字”字符。不在该集合中的任何字符都被认为是一个断词。这组字符相当有限:它只包括大写和小写的罗马字母,小数位数和下划线字符。不幸的是,重要的字符,例如“é”或“ü”,被视为断词。 |
|
|
匹配一个非单词边界。他匹配一个前后字符都是相同类型的位置:都是单词或者都不是单词。一个字符串的开始和结尾都被认为是非单词。 例如,/\B../匹配"noonday"中得'oo', 而/y\B./匹配"possibly yesterday"中得’ye‘ |
|
|
当X是处于A到Z之间的字符的时候,匹配字符串中的一个控制符。 例如,/\cM/ 匹配字符串中的 control-M (U+000D)。 |
|
|
匹配一个数字。 等价于[0-9]。 例如, /\d/ 或者 /[0-9]/ 匹配"B2 is the suite number."中的'2'。 |
|
|
匹配一个非数字字符。 等价于[^0-9]。 例如, /\D/ 或者 /[^0-9]/ 匹配"B2 is the suite number."中的'B' 。 |
|
|
匹配一个换页符 (U+000C)。 |
|
|
匹配一个换行符 (U+000A)。 |
|
|
匹配一个回车符 (U+000D)。 |
|
|
匹配一个空白字符,包括空格、制表符、换页符和换行符。 等价于[ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。 例如, /\s\w*/ 匹配"foo bar."中的' bar'。 |
|
|
匹配一个非空白字符。 等价于[^ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]。 例如, /\S\w*/ 匹配"foo bar."中的'foo'。 |
|
|
匹配一个水平制表符 (U+0009)。 |
|
|
匹配一个垂直制表符 (U+000B)。 |
|
|
匹配一个单字字符(字母、数字或者下划线)。 等价于[A-Za-z0-9_]。 例如, /\w/ 匹配 "apple," 中的 'a',"$5.28,"中的 '5' 和 "3D." 中的 '3'。 |
|
|
匹配一个非单字字符。 等价于[^A-Za-z0-9_]。 例如, /\W/ 或者 /[^A-Za-z0-9_]/ 匹配 "50%." 中的 '%'。 |
|
|
当 n 是一个正整数,一个返回引用到最后一个与有n插入的正则表达式(counting left parentheses)匹配的副字符串。 比如 /apple(,)\sorange\1/ 匹配"apple, orange, cherry, peach."中的'apple, orange,' 。 |
|
|
匹配 NULL (U+0000) 字符, 不要在这后面跟其它小数,因为 \0<digits> 是一个八进制转义序列。 |
|
|
与代码 hh 匹配字符(两个十六进制数字) |
|
|
与代码 hhhh 匹配字符(四个十六进制数字)。 |
|
|
(仅当设置了u标志时) 使用Unicode值hhhh匹配字符 (十六进制数字). |
正则表达式标志
|
标志 |
描述 |
|
g |
全局搜索。 |
|
i |
不区分大小写搜索。 |
|
m |
多行搜索。 |
|
y |
执行“粘性”搜索,匹配从目标字符串的当前位置开始,可以使用y标志。 |
使用正则表达式的方法
|
方法 |
描述 |
|
一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。 |
|
|
一个在字符串中测试是否匹配的RegExp方法,它返回true或false。 |
|
|
一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。 |
|
|
一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。 |
|
|
一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。 |
|
|
一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。 |
一个正则表达式模式使用括号,将导致相应的子匹配被记住。例如,/a(b)c /可以匹配字符串“abc”,并且记得“b”。回调这些括号中匹配的子串,使用数组元素[1],……[n]。
使用括号匹配的子字符串的数量是无限的。返回的数组中保存所有被发现的子匹配。下面的例子说明了如何使用括号的子字符串匹配。
下面的脚本使用replace()方法来转换字符串中的单词。在匹配到的替换文本中,脚本使用替代的$ 1,$ 2表示第一个和第二个括号的子字符串匹配。
var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr);
这个表达式输出 "Smith, John"。
使用正则表达式且不区分大小写将字符串中的 Microsoft 替换为 ibm:
var str = document.getElementById("demo").innerHTML;
var txt = str.replace(/microsoft/i, "ibm");
结果输出为:
Visit ibm!
使用正则表达式搜索 "Home" 字符串,且不区分大小写:
var str = "Visit Home!";
var n = str.search(/Home/i);
输出结果为:
6
var patt = /e/;
patt.test("The best things in life are free!");
字符串中含有 "e",所以该实例输出为:
true
/e/.exec("The best things in life are free!");
字符串中含有 "e",所以该实例输出为:
e
方括号用于查找某个范围内的字符:
|
表达式 |
描述 |
|
[abc] |
查找方括号之间的任何字符。 |
|
[0-9] |
查找任何从 0 至 9 的数字。 |
|
(x|y) |
查找任何以 | 分隔的选项。 |
元字符是拥有特殊含义的字符:
|
元字符 |
描述 |
|
\d |
查找数字。 |
|
\s |
查找空白字符。 |
|
\b |
匹配单词边界。 |
|
\uxxxx |
查找以十六进制数 xxxx 规定的 Unicode 字符。 |
量词:
|
量词 |
描述 |
|
n+ |
匹配任何包含至少一个 n 的字符串。 |
|
n* |
匹配任何包含零个或多个 n 的字符串。 |
|
n? |
匹配任何包含零个或一个 n 的字符串。 |
Object对象
实例属性(__proto__、prototype、constructor)
实例方法(hasOwnProperty、isPropertyOf、propertyIsEnumerable、
toLocaleString、toString、valueOf)
静态方法(Object.assign()、Object.create()、Object.defineProperties(
Object.defineProperty()、Object.freeze()、
Object.getOwnPropertyDescriptor()、
Object.getOwnPropertyNames()、Object.getPrototypeOf()、Object.setPropertyOf()、
Object.isExtensible()、Object.isFrozen()、
Object.isSealed()、Object.keys()、Object.preventExtensions()、
属性描述符(数据属性如value,writable,enumerable,configurable;访问器属性get,set)
创建对象(实例),创建方法如下:
1. 用new操作符后面跟Object的构造函数
var cat= new Object();//推荐
// var o=new Object;//这种方法有效,但不推荐用。
cat.name="sunny";
cat.legs=4;
2. 对象字面量字面量表示法(推荐)
var cat={
name:"sunny",
legs:4
}
Object类型中所具有的任何属性和方法,同样存在于具体的对象(实例)中。
Object类型的属性和方法如下:
- 构造函数:Object()
- hasOwnProperty(PropertyName):检查给定的属性是否在当前的对象实例中,注:PropertyName必须以字符串给定
- isPrototypeOf(object):检查传递的对象,是否是另一个对象的原型。注:这里牵扯到原型和原型链,所以以后具体在讲,目前大家先知道有这么个方法
- propertyIsEnumerable(PropertyName):检查给定的属性是否能用for-in 语句来枚举。注:PropertyName必须以字符串给定
- toLocaleString():返回的字符串与执行环境的地区对应
- toString():返回字符串
- valueOf():返回对象的字符串、数值或布尔值表示
对象属性的访问方法
1. 点表示法 cat.name
2. 方括号表示法:cat["name"]
注1:方括号访问的优点是:
A. 可以通过变量来访问属性
var pName="name";
alert(cat[pName]);
B. 如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以用方括号表示法。
cat["lovely brother"]="Tom"; 属性名中包含空格所以不能使用点表示法访问它
注2:访问属性推荐使用点表示法,除非没办法用点表示法的时候选择用方括号访问
Object对象,是所有JavaScript对象的超类(基类)。Object.prototype(Object的原型)定义了Js对象的基本方法和属性。
alert(Object.prototype); // [object Object]
alert(Object); // function Object { [native code] }
alert(Object()); // [object Object]
console. log(Object . prototype); {constructor: f, _dEfineGetter construct" : f Object() arguments: ( • assign: f assign() caller: ( • • • create: f create() : f, _defineSetter ha sownProp erty : f, _ LookupGEtter f defineproperties() f defineproperty() y entries: f entries freeze: f freeze getOwnPropertyDescriptor: f getOwnPropertyDescriptor() getOunPro;ertyDescriptors: f getOwnPropertyDEscriptors() f getCWnPropertyNames() f getOwnPropertySymboLs( ) getOwnPro;ertySymboZs: getPrototypeCf: f getPrototypEOf() Sis: f is() > isixtersi±le: f isExtensibLe() f isFrozen() > isSesI±d: f isSeaLed() keys: f keys() length: I name: "Obiect" preventixtersicns: f preventExtensions() prctcty;e: {constructor: f, _defineCetter Y seal: f seaL() f setPrototypEOf() values: f vaLues() _;t-cto_: f ( ) C [Scopes)]: Scopesce] hasOwnPro;erty: f hasCWnProperty() f isPrototypeOf() propertyIsEnumetäbIe: f propertyrsEnumerabLe() : f, _defineSetter hasCqn Property : f, I ookupGetter_ toLozsI±String: f toLocaLeString() toStrirg: f toString() valueCF: f VGLueOf() _d : f _ defineGEtter o define Setter Setter " v:shapes="图片_x0020_56">
2. 构造函数(Object()、Object(value))
2.1 new Object() :返回一个Object实例
2.2 new Object(value) :根据value的值,返回不同的对象(Number、Boolean、String)
参数:
①value {number | bool | string} :一个数字、布尔值或者字符串
返回值:
{Number、Boolean、String} 返回一个转换后的对象
示例 :
var o = new Object(123);
console.log(o); // => Number对象
o = new Object(true);
console.log(o); // => Boolean对象
o = new Object('abc');
console.log(o); // => String对象
而alert(o); // 弹出123
3. 实例属性(__proto__、prototype、constructor)
3.1 __proto__ :设置或返回对象的原型对象(IE中不支持此属性)
说明:
1) 赋值时,对象实例继承新原型的所有方法和属性,以及新原型的原型链中的所有方法和属性。
2) 属性名称以两个下划线开始和结束。
3) 对象实例的__proto__ == 或===对象原型(类/构造函数)的prototype
示例:
function People(name) {
this.name = name;
}
function Student(age) {
this.age = age;
}
Student.prototype = new People(); // 设置Student的原型为People对象
var s = new Student(22);
console.log(s.__proto__); // => People 对象
console.log(Student.prototype); // => People 对象
console.log(s.__proto__ == Student.prototype); // => true
console.log(s.__proto__ === Student.prototype); // => true
// 2.对象直接量
var p = {}; // 等于new Object()
console.log(p.__proto__ == Object.prototype); // => true
console.log(p.__proto__ === Object.prototype); // => true
3.2 prototype :设置或返回对象原型(类/构造函数)的原型对象
说明:
1) prototype为对象原型(类/构造函数)的属性。__proto__是对象实例的属性。
2) JS内置对象(Array、Date等对象)都有一个只读的prototype属性。 可将属性和方法添加到原型中,但不能为内置对象分配其他原型。
3) 自定义对象的prototype属性可进行读写操作。
示例:
var Student = function (name) {
this.name = name;
};
// 给Student的原型添加一个sayHello方法
Student.prototype.sayHello = function () {
alert('Hello,' + this.name);
}
var st = new Student('张三'); // 初始化对象st
console.log(st.name); // => 张三
st.sayHello(); // 弹出:Hello,张三
3.3 constructor :表示创建此对象的构造函数
说明:
1) 设置或返回创建此对象的构造函数。
2) 若一个对象有多层继承,将返回最先调用的构造函数。
3) obj.constructor.prototype 可表示对象的原型。
示例:
// 1.内置对象
var str = 'abc';
console.log(str.constructor); // => function String 构造函数
var o = {};
console.log(o.constructor); // => function Object 构造函数
Chrome控制台显示 ƒ Object() { [native code] },跟一开始的console.log(Object)一样,
所以也就能理解obj.constructor.prototype 可表示对象的原型了
// 2.自定义对象多层继承 :constructor返回最先调用的构造函数
function People(name) {
this.name = name; // s对象初始化时,先调用People构造函数,再调用Student构造函数
console.log('People调用');
}
function Student(age) {
this.age = age;
console.log('Student调用');
}
Student.prototype = new People(); // 设置Student的原型为People对象
var s = new Student(22);
console.log(s.constructor); // => function People 构造函数
总结:__proto__、prototype、constructor 的关系
说明:
1) 对象实例的__proto__ 等于 对象原型(类/构造函数)的prototype
2) 对象实例的constructor 等于 对象原型(类/构造函数),所以obj.constructor.prototype 可表示对象的原型。
示例:
|
|
var o = {}; console.log(o.__proto__ === Object.prototype); // true :对象的__proto__等于类的prototype console.log(o.constructor === Object); // true :对象的constructor 等于 类 console.log(o.constructor.prototype === Object.prototype); // true :o.constructor.prototype 可表示对象的原型。 |
4. 实例方法(hasOwnProperty、isPropertyOf、propertyIsEnumerable、
toLocaleString、toString、valueOf)
4.1 hasOwnProperty(propertyName) :判断对象是否拥有一个指定名称的实例属性(非继承)
参数:
①propertyName {string} :属性名称。
返回值:
{bool} 判断对象是否拥有一个指定名称的本地定义(非继承)的属性;此方法不会检查对象原型链中的属性。
true :属性为对象的实例属性,非继承。
false :属性不为对象的实例属性。
示例 :
// 1.Object对象
var o = new Object();
o.name = '自定义属性'; // 定义一个实例属性
console.log(o.hasOwnProperty('name')); // => true:name属性为实例o自己定义的,而非继承
console.log(o.hasOwnProperty('toString')); // => false:toString为继承属性
// 2.自定义对象
var Student = function (name) {
this.name = name;
};
// 给Student的原型添加一个sayHello方法
Student.prototype.sayHello = function () {
alert('Hello,' + this.name);
}
// 给Student的原型添加一个age属性
Student.prototype.age = '';
var st = new Student('张三'); // 初始化对象st
console.log(st.hasOwnProperty('name')); // => true :调用构造函数时,通过this.name附加到实例对象上
console.log(st.hasOwnProperty('sayHello')); // => false :sayHello方法为原型上的成员
console.log(st.hasOwnProperty('age')); // => false :age属性为原型上的成员
4.2 isPrototypeOf(obejct) :判断某个原型是否出现在对象的原型链中
语法:
prototype.isPrototypeOf(object)
参数:
①obejct {object} :被检测的对象。
返回值:
{bool} 返回某个原型是否出现在对象的原型链中
true :是
false :不是
示例 :
// 1.Obejct对象
var o = new Object();
console.log(Object.prototype.isPrototypeOf(o)); // => true :o为Obejct一个对象
// 2.Array
var array = [1, 2, 3];
console.log(Array.prototype.isPrototypeOf(array)); // => true :数组原型
console.log(Object.prototype.isPrototypeOf(array)); // => true :Object是所有对象的基原型
// 3.自定义对象
var People = function () {
}
var Student = function () {
}
// 设置Student类的原型为People
Student.prototype = new People();
var st = new Student();
console.log(Student.prototype.isPrototypeOf(st)); // => true :st为Student一个对象
console.log(People.prototype.isPrototypeOf(st)); // => true :Student的原型为People
console.log(Object.prototype.isPrototypeOf(st)); // =>true :Object是所有对象的基原型
4.3 propertyIsEnumerable(propertyName) :
判断指定名称的属性是否为实例属性并且是可枚举的(可用for/in循环枚举)
参数:
①propertyName {string} :属性名称
返回值:
{bool} 判断属性是否为实例属性并且是可枚举的(可用for/in循环枚举),不考虑原型链中的成员。
true :是
false :不是
示例 :
// 1.Array对象
var array = [1, 2, 3];
array.name = 'Array';
console.log(array.propertyIsEnumerable('name')); // => true :name属性为实例属性
console.log(array.propertyIsEnumerable('join')); // => false :join方法继承自Array
console.log(array.propertyIsEnumerable('length')); // => false :length属性继承自Array
console.log(array.propertyIsEnumerable('toString')); // => false :toString方法继承自Object
// 2.自定义对象
var Student = function (name) {
this.name = name;
}
// 定义一个原型方法
Student.prototype.sayHello = function () {
alert('Hello' + this.name);
};
var a = new Student('tom');
console.log(a.propertyIsEnumerable('name')); // => true :name为自身定义的实例属性
console.log(a.propertyIsEnumerable('age')); // => false :age属性不存在,也返回false
console.log(a.propertyIsEnumerable('sayHello')); // => false :sayHello属于原型方法
4.4 toLocaleString() :返回当前对象的一个本地化的字符串表示
4.5 toString() :返回当前对象的一个字符串表示形式
4.6 valueOf() :返回当前对象的原始值
参数:无
返回值:
{object} 返回当前对象关联的原始值,若没有相关联的值,则返回对象本身
示例 :
var a = [1, 2, 3];
console.log(a.valueOf()); // => [1, 2, 3]
var b = true;
console.log(b.valueOf()); // => true
var c = {};
console.log(c.valueOf()); // => Object {}
var s = 'abc';
console.log(s.valueOf()); // => abc
// 自定义个对象,重写valueOf
var customObject = {};
customObject.valueOf = function () {
return '自定义对象';
}
console.log(customObject.valueOf()); // => 自定义对象
5. 静态方法(Object.assign()、Object.create()、Object.defineProperties()、
Object.defineProperty()、Object.freeze()、
Object.getOwnPropertyDescriptor()、
Object.getOwnPropertyNames()、Object.getPrototypeOf()、Object.setPropertyOf()、
Object.isExtensible()、Object.isFrozen()、
Object.isSealed()、Object.keys()、Object.preventExtensions()、
Object.seal())
Object.assign(target, ...sources)
将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。合成对象,共同属性会合并
Object.setPropertyOf()
5.1 Object.create(prototype, propertyDescriptor):
创建并返回一个指定原型和指定属性的对象
参数:
①prototype {prototype} :返回对象的原型,可以为null。若为null,对象的原型为undefined。
②propertyDescriptor {propertyDescriptor} 可选:属性描述符。
属性描述符:设置属性的一系列特性;
语法格式:
propertyName: {
value: '', // 设置此属性的值
writable: true, // 设置此属性是否可写入;默认为false:只读
enumerable: true, // 设置此属性是否可枚举(通过for/in预付);默认为false:不可枚举
configurable: true // 设置此属性是否可配置;如:是否可以修改属性的特性及删除属性。默认为false
}
返回值:
{object} 返回一个指定原型和指定属性的对象
示例 :
// 建立个自定义对象,设置name和age属性
var obj = Object.create(null, {
name: {
value: 'tom',
writable: true,
enumerable: true,
configurable: true
},
age: {
value: 22
}
});
console.log(obj.name); // => tom
console.log(obj.age); // => 22
obj.age = 28;
console.log(obj.age); // => 22 :age属性的writable默认为false,此属性为只读
5.2 Object.defineProperties(object, propertyDescriptor) :添加/修改对象一个或多个属性的特性
参数:
①object {object} :对象
②propertyDescriptor {propertyDescriptor} 属性描述符。
说明:
若对象包含此属性,则是修改此属性的特性;否则为为对象添加此属性。
示例 :
var obj = {};
// 为对象添加name和age属性
Object.defineProperties(obj, {
name: {
value: 'tom',
enumerable: true
},
age: {
value: 22,
enumerable: true
}
});
for (p in obj) {
console.log(p); // => name、age :输出name和age属性
}
5.3 Object.defineProperty(obj, propertyName, propertyDescriptor) :添加/修改对象指定属性的特性
参数:
①object {object} :对象
②propertyName {string} :属性的名称
③propertyDescriptor {propertyDescriptor} 属性描述符。
说明 :
若对象包含此属性,则是修改此属性的特性;否则为添加此属性。
示例:
var obj = {};
// 添加一个name属性
Object.defineProperty(obj, 'name', {
value: 'tom',
writable: true,
enumerable: true,
configurable:true
}
);
console.log(obj.name); // => tom :输出name属性的value的值
5.4 Object.freeze(object) :
冻结对象,使其不能添加属性以及无法对现有的实例属性进行特性更改、值修改、属性删除等操作
参数:
①object {object} :对象
说明 :
1) 此操作不可逆,冻结后无法进行解封。
2) 只影响实例属性,不影响原型属性。
示例:
var obj = {
name: 'tom',
age: 22
};
Object.freeze(obj); // 冻结对象
obj.email = '123@qq.com';
console.log(obj.email); // undefined :无法添加属性
obj.age = 25;
console.log(obj.age); // 22 :无法设置属性的值
5.5 Object.getOwnPropertyDescriptor(object, propertyName) :
返回对象属性的描述符
参数:
①object {object} :对象
②propertyName {propertyName} 属性名称
返回值:
{propertyDescriptor} 属性描述符对象
示例 :
var obj = {
name: 'tom',
age: 22
};
var propertyDes = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(propertyDes); // => Object {value: "tom", writable: true, enumerable: true, configurable: true} :输出描述符对象
5.6 Object.getOwnPropertyNames(object) :
返回一个数组,包含对象的所有实例属性和方法,不包含原型继承的属性和方法
参数:
①object {object} :对象
返回值:
{Array} 一个数组,包含对象的所有实例属性和方法,不包含原型继承的属性和方法
示例 :
|
1 2 3 4 5 6 7 8 |
var obj = { name: 'tom', age: 22, sayHello: function () { alert('Hello' + this.name); } }; console.log(Object.getOwnPropertyNames(obj)); // => ["name", "age", "sayHello"] :返回对象的实例成员 |
5.7 Object.getPrototypeOf(object) :返回对象的上一级原型
参数:
①object {object} :对象
返回值:
{object} 返回原型对象
示例 :
// 1.对象直接量
var obj = {
name: 'tom',
age: 22,
sayHello: function () {
alert('Hello' + this.name);
}
};
console.log(Object.getPrototypeOf(obj)); // => Object 对象:对象直接量的原型为Object
// 2.自定义对象
var People = function (name) {
this.name = name;
};
var p = new People('tom');
var people = Object.getPrototypeOf(p);
console.log(people); // => People 对象:new 创建的对象使用构造函数的prototype属性作为他们的原型
console.log(Object.getPrototypeOf(people)); // => Object 对象:原型People的原型为Object
5.8 Object.isExtensible(object) :判断是否可向对象添加新的属性
5.9 Object.isFrozen(object) :判断对象是否冻结;true:不能修改对象的现有属性特性和值并且不能添加新的属性
5.10 Object.isSealed(object) :判断对象是否封闭;true:不能修改对象的现有属性特性并且不能添加新的属性
5.11 Object.keys(object) :返回一个数组,包含对象的可枚举的实例属性名称
参数:
①object {object} :对象
返回值:
{Array} 返回一个数组,包含对象可枚举的实例属性名称
说明:
此方法与getOwnPropertyNames()类似,但getOwnPropertyNames()包含了可枚举和不可枚举的成员
示例 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var obj = { name: 'tom', age: 22, sayHello: function () { alert('Hello' + this.name); } };
// 1)getOwnPropertyNames与keys方法返回的内容都相同 console.log(Object.getOwnPropertyNames(obj)); // => ["name", "age", "sayHello"] :返回对象的所有实例成员 console.log(Object.keys(obj)); // => ["name", "age", "sayHello"] :返回对象的所有可枚举成员
// 设置对象的name属性不可枚举 Object.defineProperty(obj, 'name', { enumerable: false } );
// 2)keys方法,只包含可枚举成员 console.log(Object.getOwnPropertyNames(obj)); // => ["name", "age", "sayHello"] :返回对象的所有实例成员 console.log(Object.keys(obj)); // => ["age", "sayHello"] :返回对象的所有可枚举成员 |
5.12 Object.preventExtensions(object) :设置对象不能添加新的属性
参数:
①object {object} :对象
返回值:
{object} 返回此对象
示例 :
|
1 2 3 4 5 6 7 |
var obj = { name: 'tom', age: 22 }; Object.preventExtensions(obj); // 设置对象不能添加新的属性 obj.email = '123@qq.com'; console.log(obj.email); // => undefined :无法向对象添加新的属性 |
5.13 Object.seal(object) :密封对象,使其无法修改现有属性的特性以及不能添加新的属性
参数:
①object {object} :对象
返回值:
{object} 返回此对象
示例 :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var obj = { name: 'tom', age: 22 }; Object.seal(obj); // 密封对象 obj.email = '123@qq.com'; console.log(obj.email); // => undefined :无法向对象添加新的属性
// 报异常:无法修改对象属性的特性 Object.defineProperty(obj, 'name', { enumerable: false } ); |
6.属性描述符(数据属性如value,writable,enumerable,configurable;访问器属性get,set)
分为数据属性和访问器属性;
两者可相互转换,若转换后未设置enumerable和configurable特性(两类属性描述符都包含这2个特性),将默认采用转换前的值。
6.1 数据属性
说明:包含属性的操作特性;如:设置值、是否可枚举等等
|
特性名称 |
描述 |
默认值 |
|
value |
设置属性的值 |
undefined |
|
writable |
是否可修改属性的值;true:可修改属性的值;false:不可修改属性的值 |
false |
|
enumerable |
是否可枚举属性;true:可枚举,可通过for/in语句枚举属性;false:不可枚举 |
false |
|
configurable |
是否可修改属性的特性;true:可修改属性的特性(如把writable从false改为true);false:不可修改属性的特性 |
false |
默认值:
1)在使用Object.defineProperty、Object.defineProperties 或 Object.create 函数的情况下添加数据属性,writable、enumerable和configurable默认值为false。
2)使用对象直接量创建的属性,writable、enumerable和configurable特性默认为true。
示例:
|
1 2 3 4 5 6 7 8 9 10 11 |
// 1)对象直接量;属性特性默认为true var o1 = { name: 'tom' }; console.log(Object.getOwnPropertyDescriptor(o1, 'name')); // => Object {value: "tom", writable: true, enumerable: true, configurable: true}
// 2)通过Object.create创建,属性特性默认为false var o2 = Object.create(null, { name: {value:'tom'} }); console.log(Object.getOwnPropertyDescriptor(o2, 'name')); // => Object {value: "tom", writable: false, enumerable: false, configurable: false} |
6.2 访问器属性
说明:设置属性的访问方式;set、get特性等
|
特性名称 |
描述 |
默认值 |
|
get |
属性的返回值函数 |
undefined |
|
set |
属性的设置值函数;含有一个赋值参数 |
undefined |
|
enumerable |
是否可枚举属性;true:可枚举,可通过for/in语句枚举属性;false:不可枚举 |
false |
|
configurable |
是否可修改属性的特性;true:可修改属性的特性(如把writable从false改为true);false:不可修改属性的特性 |
false |
示例:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var obj = {};
// 添加一个属性,并设置为访问器属性 Object.defineProperty(obj, "name", { get: function () { return this._name; // get和set里的变量不要使用属性,如:属性为name,get和set用的是_name }, set: function (x) { if (isNaN(x)) { this._name = x; } else { this._name = 'name不能为纯数字'; } }, enumerable: true, configurable: true });
console.log(Object.getOwnPropertyDescriptor(obj, 'name')); // => Object {get: function, set: function, enumerable: true, configurable: true} obj.name = '12'; console.log(obj.name); // => name不能为纯数字 |
单单js运行方式
(1) 控制台
(2)在线js编辑器RunJS、JSBin等(推荐)
(3)命令行:node 文件名(加不加js都可以) 这种太麻烦了
(4) VScode把program 换成"program": "${file}"
一开始 配置错了,改成${file} 就解决了,就是运行当前文件
《编写可维护的JavaScript》学习笔记
统一编程风格:
编程风格(style guideline)、编码规范(code convention),编程风格是编码规范的一种。
编码规范还包括编程最佳实践、文件和目录的规划、注释等。
JSHint是JSLint的一个分支项目。JSHint较宽松,当出现语法错误时,可以关掉编程风格检查(可配置的选项很多,JSLint较少)。
一、格式化:
(1)缩进:建议在编辑器中配置敲入Tab键时插入4个空格。
(2)语句结尾:建议不要省略分号,虽然分析器有自动分号插入(Automatic Semicolon Insertion, ASI)机制。
(3)行的长度:最长不应当超过80个字符。
(4)换行:通常在运算符(例如逗号)后换行,下一行会增加两个层级(例如8个字符)的缩进。
(5)空行:语义不相关用空行分隔,有关联的代码展现在一起。
下面场景添加空行挺好:
在方法之间。
在方法中的局部变量(localvariable)和第一条语句之间。
在多行或单行注释之前·
在方法内的逻辑片段之间插入空行,提高可读性。
(6)命名:驼峰式命名法 大驼峰命名法(Pascal case) 小驼峰命名法(Camel case)
6.1 变量和函数:变量名前缀是名词,函数名前缀是动词。foo、bar、tmp之类没有意义的命名尽量避免。
约定:
|
动词 |
含义 |
|
can |
函数返回一个布尔值 |
|
has |
函数返回一个布尔值 |
|
is |
函数返回一个布尔值 |
|
get |
函数返回一个非布尔值 |
|
set |
函数用来保存一个值 |
jQuery显然并没有遵循这种函数命名约定,一部分原因在于jQuery中方法的使用方式,很多方法同时用作getter和setter.
比如,$("body").attr("class")可以取到class属性的值,而$("body").attr("class","selected")可以给class属性赋值。
尽管如此,还是推荐使用动词作为函数名前缀。
6.2 常量:都大写,用下划线分隔。
6.3 构造函数:大驼峰命名法。
(7)直接量
7.1 字符串
// 合法的JavaScript代码
Var name = "Nicholas says, \"Hi.\"";
// 也是合法的JavaScript代码
Var name= 'Nicholas says, "Hi"';
在使用双引号括起来的字符串里需要对双引号进行转义,
而在使用单引号括起来的字符串里则不必如此。
关于字符串还有另外一个问题需要注意,即创建多行字符串。这个特性并非来自JavaScript语言本身,
却在几乎所有的(JavaScript)引擎中正常工作。
// 不好的写法
var longstring = "Here's the story, Of a man \
named Brady . " ;
// Good
var longstring = "Here ' S the story, Of a man
"named Brady .
7.2 数字
// 不推荐的小数写法:没有整数部分
var price = .1;
7.3 null
/ / 不好的写法:检测是否传入了参数
function dosomething(argl, arg2, arg3, arg4) {
if (arg4 != null) {
doSomethingE1se () ;
}
}
理解null最好的方式是将它当做对象的占位符(placeholder)。
7.4 undefined
未声明的变量和未初始化的变量,typeof运算结果都是undefined
// foo未被声明
var person;
console.log(typeof person); // "undefined"
console. log(typeof foo); // "undefined"
var person = null;
console.log(typeof person); // "object"
将变量初始值赋值为null表明了这个变量的意图,它最终很可能赋值为对象。
typeof运算符运算null的类型时返回"object",这样就可以和undefined区分开了。
7.5 建议用对象直接量
7.6 建议用数组直接量
二、注释
空格:双斜杠后、星号后
空行:多行注释前
缩进
// 好的写法
// if (condition) {
// doSomething();
// thenDoSomethingEIse();
// }
// 不好的写法:这里应当用多行注释
// 接下来的这段代码非常难,那么,让我详细解释一下
// 这段代码的作用是首先判断条件是否为真
// 只有为真时才会执行,这里的条件是通过
单行注释
多行注释(Java的多行注释每一行都有星号)
文档注释(JavaDoc风格)
初始化某变量这种显而易见的注释就不用写了,但变量改变有什么特殊意义可以写。
要添加注释:
难以理解的代码
可能被认为错误的代码
浏览器特效hack
三、语句和表达式
1、if的花括号要加,而且不要写成一行:if (condition) { doSomething(); }
所有块语句都不要省略花括号。
if
for
while
do… while…
try...catch...finally …
推荐花括号的对齐方式为第一行末尾,不要另起一行。
块语句间隔建议:在括左圆括号之前和右圆括号之后各添加一个空格。比如:
if (condition) {
dosomething();
}
2、switch:
(1)缩进和第二个case开始,每个case语句前加空行
(2)case可连续执行,即
case "first":
case "second":
// …
break;
(3)default中如果没有逻辑可以省略
3、with
推荐避免使用with语句
with语句可以更改包含的上下文解析变量的方式。通过with可以用局部变量和函数的形式来访问特定对象的属性和方法,
这样就可以将对象前缀统统省略掉。如果一段代码中书写了很多对象成员,则可以使用with语句来缩短这段代码。
var book = {title: "Maintainable JavaScript" ,author: "Nicholas C. "The book is {msg Zees"); var msg = *author;} "The book is Maintainable JavaScript by Nicholas C. title; msg Zakas " " by " " v:shapes="图片_x0020_52">
在这个例子中,with语句花括号内的代码中的book的属性都是通过局部变量来读取的,以增强标识符的解析。
问题是我们很难分辨出title和author出现在哪个位置,也难分辨出message到底是局部变量还是book的一个属性。
实际上这种困惑对开发者的影响更甚,JavaScript引擎和压缩工具无法对这段代码进行优化,因为它们无法猜出代码的正确含义。
在严格模式中,with语句是被明确禁止的,如果使用则报语法错误。
4、for
遍历数组成员
尽量避免用continue,可以修改条件语句即可达到同样效果。
5、for-in
遍历对象属性(还会遍历从原型继承来的属性)
最好用hasOwnProperty()方法来为for-in循环过滤出实例属性。
var prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
console.log("Property name is " + prop);
console.log("Property value is " + object[prop]);
}
}
四、变量、函数和运算符
JavaScript编程的本质是编写一个个函数来完成任务。
10+undefined 返回NaN
4.1 变量声明
推荐单var语句
4.2 函数声明
和变量声明一样,函数声明也会被JavaScript引擎提前。因此,在代码中函数的调用可以出现在函数声明之前。
// 不推荐
doSomething ();
function doSomething() {
alert("cxf");
}
这段代码是可以正常运行的,因为JavaScnpt引擎将这段代码解析为:
function doSomething() {
alert("cxf");
}
doSomething ();
由于JavaScript的这种行为,我们推荐总是先声明JavaScript函数然后使用函数。
函数声明不应当出现在语句块之内。
4.3 立即调用的函数
立即执行的函数要加圆括号
var value = (function()
// 函数体
return {
message : "cxf"
}
}());
4.4 严格模式
最好不要在全局作用域中使用“use strict”
// 不好的写法-全局的严格模式
"use strict";
function doSomething() {
//…
}
// 好的写法
function doSomething0
"usestrict";
//…
如果你希望在多个文件中应用严格模式而不必写很多行“use strict”的话,可以使
用立即执行的函数。
/ / 好 的 写 法
(function () {
"use strict";
function doSomething () {
/ / …
}
function doSomethingElse () {
/ / …
}
})();
4.5 相等
推荐总是用===和 !==
当发生强制类型转换时,字符串会被转换为数字,类似使用Number()转换函数。
如果一个布尔值和数字比较,布尔值会首先转换为数字,然后进行比较。
如果其中一个值是对象而另一个不是,则会首先调用对象的valueOf()方法,得到原始类型值再进行比较。
如果没有定义valueOf(),则调用toString()。
4.6 eval()
4.7
…
对于已存在的JavaScript对象的方法:不覆盖;不新增;不删除。
修改对象(对象扩充)最受欢迎的形式是继承。如果一种类型的对象已经做到了你想要的大多数工作,那么继承自它,然后再新增一些功能即可。
继承包括基于对象的继承(也常被叫做原型继承)和基于类型的继承。
基于对象的继承(也常被叫做原型继承):一个对象继承另外一个对象不需要调用构造函数,依赖于原型。
ES5的Object.create()方法是实现这种继承的最简单的方式。
var person = {
name: "cxf",
sayName: function() {
console.log(this.name);
}
};
var myPerson = Object.create(person); // 等价于myPerson.prototype = person; 这两种方法都可以让myPerson能够访问person的属性和方法。
myPerson.sayName(); // cxf
这个例子创建了一个新对象myPerson,它继承自person。
基于类型的继承是通过构造函数而非对象。基于类型的继承一般需要两步:首先,原型继承,然后,构造器继承。
(构造器继承是调用超类的构造函数时传入新建的对象作为其this的值)
function MyError (message) {
this.message = message;
}
MyError.prototype = new Error();
function Person (name) {
this.name;
}
function Author (name) {
Person.call(this, name);
}
Author.prototype = new Person();
包装器模式(也叫门面模式)
阻止修改
程度从浅到深依次为:
(1)防止扩展
禁止“添加”
(2)密封
禁止“添加”+“删除”
(3)冻结
禁止“添加”+“删除”+“修改”
lambda表达式是匿名函数,但是匿名函数不全是使用lambda表达式来写的。
JavaScript书籍阅读笔记
在函数开始执行时创建所有的局部变量,称为提升。
规范代码,为扩展做好准备。eg:全局变量放开头、函数放在一起,局部变量放在函数体开头。
修改数组元素:flavor[3] = "chocolate";
属性length
索引可以是一个变量:
eg:var rand = Math.floor(Math.random() * words.length);
alert(words[rand]);
数组元素可以是任何JavaScript值(数字、字符串、布尔值、其他数组、对象等)。
访问索引太大或太小(小于0)的数组元素时,结果都是undefined。
稀疏数组没赋值处都是undefined,长度是最大索引+1。
未初始化的变量的值是undefined,没有值的变量也会占用计算机内存。
myArray[myArray.length-1]获取最后一个数组元素。
while(answer != "forty") 等价于 for(;answer != "forty";)
if(myarr[i] == undefined) undefined是一个值,不是一个字符串,不能加引号
i = i + 1 等价于 i++
可以省略初始值,创建一个空数组 var arr = [];
给数组添加新元素可以给指定索引处的元素赋值(可“稀疏”)或push方法。
数组是特殊的对象,对象可以有关联的函数(eg:push()),用于操作对象。
[]属于字面量,还可以new Array(3)
对象变量又叫引用变量
重构(refactor)指的是不改变代码功能的情况下,对齐进行重新组织,通常是函数返回值。
对象有属性和行为,每个属性都有名称和值。
属性名可以是任何字符串,包含空格的字符串用引号括起来。
在同一个对象中,不能包含两个同名的属性。
最后一个属性名和属性值对后,不能添加逗号,现代浏览器大多数不会导致错误,旧版本会导致JS停止执行。
Geolocation
Web Workers
元 累 , 那 是 不 是 就 不 能 向 worker 中 添 加 其 他 脚 本 了 " v:shapes="图片_x0020_2">
浙公网安备 33010602011771号