写在前面
此文作为笔记所用,且有的地方可能有点小错误什么的,欢迎大佬们指点或指正,小花在此谢过~
1. JS中浅拷贝及深拷贝
数组浅拷贝代码举例:
var arr = ["One","Two","Three"];
var arrto = arr;
arrto[1] = "test";
document.wrirteln("数值的原始值:" + arr + "<br />"); //Export:数组的原始值:One,test,Three
document.wrirteln("数值的原始值:" + arrto + "<br />"); //Export:数组的新值:One,test,Three
-
解决数组浅拷贝的方法有:
- arr.slice(0) 得到的是一个新数组
- var arrtooo = arr.concat();
对象的深拷贝(将对象中属性遍历一次得到一个新数组):
方法一:
var deepCopy = function(source){
var result = {};
for (var key in source){
result[key] = typeof source[key] === 'object'?deepCopy(source[key]):source[key];
}
return result;
}
方法二:
str = JSON.stringify(obj), //系列化对象
newobj = JSON.parse(str); //还原
将它封装成一个函数之后:
function jsonClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
var clone = jsonClone(obj);
2. 关于chrome无法访问XMLHttpRequest
关于chrome无法访问XMLHttpRequest,原因是chrome 到安全性的问题,限制了本地跨域,可用的方式有,利用jQuery来改写,还有就是在chrome图标属性的目标项更改参数设置为"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" (此处有一个空格)--args --disable-web-security
3. JSON的输出方式
//此部分不重要,初学者可观看
var data01 = {
"total_page": 2,
"cover_url_large": "xxx",
"tracks": [{
"id": 237730,
"track_title": "张杰 - 无情的情书(live版)",
"announcer": {
"nickname": "tiny121",
},
"duration": 310,
"subordinated_album": {
"album_title": "tiny550_album 001",
},
"source": 2,
},
{
"track_title": "张杰 - 无情的情书(...)",
"announcer": {
"nickname": "dgfsgdfdhfgdsgfhdsgu",
},
"duration": 310,
"subordinated_album": {
"id": 86492,
},
"source": 2,
}
]
}
document.write(data01.tracks[0].track_title);
document.write(data01.tracks[0].announcer.nickname);
document.write(data01.tracks[1].announcer.nickname);
document.write(data01.tracks[1].track_title);
//其中data01为json名,tracks为一个数组包含多个对象
4. 自执行匿名函数(IIFE)
- 常见格式:(function() { /* code */ })();
- 解释:包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命名函数,括号内为匿名函数的参数。
- 作用:可以用它创建命名空间,只要把自己所有的代码都写在这个特殊的函数包装内,那么外部就不能访问,除非你允许(变量前加上window,这样该函数或变量就成为全局)。各JavaScript库的代码也基本是这种组织形式。
- 最大的用途是创建闭包
注意:函数声明后面不允许在后面直接使用小括号
函数声明和函数表达式不同之处在于,一、Javascript引擎在解析javascript代码时会‘函数声明提升’(Function declaration Hoisting)当前执行环境(作用域)上的函数声明,而函数表达式必须等到Javascirtp引擎执行到它所在行时,才会从上而下一行一行地解析函 数表达式,二、函数表达式后面可以加括号立即调用该函数,函数声明不可以,只能以fnName()形式调用 。
fnName();
function fnName(){
...
} //正常,因为‘提升’了函数说明,函数调用可在函数声明之前
fnName();
var fnName = function(){
...
}//报错,变量fnName还未保存对函数的应用,函数调用必须在函数表达式之后
var fnName = function(){
alert('Hello World');
}(); //函数表达式后面加括号,当JavaScript引擎解析到此处时能立即调用函数
function fnName(){
alert('Hello World');
}(); //不会报错,但是JavaScript引擎只解析函数声明,忽略后面的括号,函数声明不会被调用
function(){
console.log('Hello World');
}(); //语法错误,虽然匿名函数属于函数表达式,但是未进行赋值操作,
//所以JavaScript引擎开头的function关键字当做函数声明,报错:需要一个函数名
javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖 掉,根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,“容器”内部可以访问外部的变 量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。
5.dataset 自定义属性
- 这里的data-前缀就被称为data属性,其可以通过脚本进行定义,也可以应用CSS属性选择器进行样式设置。数量不受限制,在控制和渲染数据的时候提供了非常强大的控制。
var expenseday2 = document.getElementById('day2-meal-expense');
var typeOfDrink = expenseday2.dataset.drink;
- 删除data属性:delete expenseday2.dataset.meal;
- 添加data属性:expenseday2.dataset.dessert = 'icecream';
- data在css中的使用: .mm[data-name='张含韵']{ }
6. 迭代器模式
提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示。
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 访问一个聚合对象的内容而无需暴露它的内部表示。
- 遍历的同时更改迭代器所在的集合结构可能会导致问题
7. map()和filter()
- filter是满足条件的留下,是对原数组的过滤;filter 是根据返回的值是否为真来判断是否保留元素
- map则是对原数组的加工,映射成一一映射的新数组
function pp(x){return x % 2;}
function px(x){return x % 2;}
var m = xx.map(pp);
var f = xx.filter(px);
- array.map(callback[, thisObject]);
callback : 从当前的元素函数产生新的数组的元素。
thisObject : 对象作为该执行回调时使用
8. 闭包
闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
- 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。(解决方法是,在退出函数之前,将不使用的局部变量全部删除)
- 闭包会在父函数外部,改变父函数内部变量的值。
9. ES5中的bind()方法
bind和call以及apply一样,都是可以改变上下文的this指向的。不同的是,call和apply一样,直接引用在方法上,而bind绑定this后返回一个方法,但内部核心还是apply。