JS第三次准备

  • 你觉得js是一门怎样的语言,它与你学过的其他语言有什么不同

  • 变量类型

  • js如何判断变量数据类型

  • dom节点获取,及其特性

  • innerHTML和innerText区别

  • 数组中的每个值至多出现1次的处理方法

  • 了解伪数组和数组

  • 各种原生方法

  • html、dom0、dom2是如何注册事件

  • 事件流

  • 事件委托(代理)

  • 异步同步

  • ajax

  • 请求接口跨域了怎么解决

  • 变量声明提升(有可能有个题)

  • 作用域

  • 克隆对象

  • this

  • 修改this指向的方法

  • 柯里化

  • 闭包

  • js运行机制

  • 原型链

  • 对象的继承机制

你觉得js是一门怎样的语言,它与你学过的其他语言有什么不同

alert() 与 console.log() 的区别

alter()

  1. 对代码运行有阻塞作用,在弹出框输出,不点击确定,后续代码无法继续执行

  2. alert()只能输出string,如果alert输出的是对象会自动调用toString()方法 e.g. alert([1,2,3]);//’1,2,3’

  3. alert不支持多个参数的写法,只能输出第一个值 e.g. alert(1,2,3);//1^

console.log()

  1. 对代码运行无阻塞作用,在打印台输出,

  2. 可以打印任何类型的数据 e.g. console.log([1,2,3]);//[1,2,3]

  3. 支持多个参数的写法 e.g. console.log(1,2,3)// 1 2 3

变量类型

js如何判断变量数据类型

Object.prototype.toString()有一个妙用,如果我们以某个特别的对象为上下文来调用该函数,它会返回正确的类型。我们需要做的就是手动处理其返回的字符串,最终便能获得typeof应该返回的正确字符串。

可以用来区分:Boolean, Number, String, Function, Array, Date, RegExp, Object, Error等等。

jQuery.type()就是这样实现的。以下代码从jQuery源码中抽取出来,可以直接用。

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n108" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var class2type = {} ;
"Boolean Number String Function Array Date RegExp Object Error".split(" ").forEach(function(e,i){
class2type[ "[object " + e + "]" ] = e.toLowerCase();
}) ;
//当然为了兼容IE低版本,forEach需要一个polyfill,不作细谈了。
function _typeof(obj){
if ( obj == null ){
return String( obj );
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[ class2type.toString.call(obj) ] || "object" :
typeof obj;
}</pre>


JavaScript Garden整理出来了如下表格:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n112" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">Value function typeof

"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object
new RegExp("meow") RegExp object
{} Object object
new Object() Object object </pre>

所以我们一般用“鸭子类型”来做流程控制


公认的靠谱解法是 Object.prototype.toString.call(x) === '[object Array]'

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n118" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">console.log(Object.prototype.toString.call([1,2,3])=='[object Array]');
console.log(Object.prototype.toString.call(new Date())=='[object Date]');
console.log(Object.prototype.toString.call(3)=='[object Number]');
console.log(Object.prototype.toString.call('1')=='[object String]');
console.log(Object.prototype.toString.call(function(){})=='[object Function]');</pre>


typeof: 返回的是string类形

​ 判断基本数据类型:string、number、boolean、function、undefined类 ,对数组、对象、null类型都统统打印的是object类型

instanceof: 返回的是boolean类型(可判断数组类型)

​ 判断依据:检测对象的原型链上是否有构造函数的prototype属性。

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n128" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false"><span style="font-size:14px;">function Person(){
}
function Student(){
}
Student.prototype=new Person();
Student.prototype.constructor=Student; //注:原型替换的过程(也就是继承)会失去原型对象的constructor属性,所以我们需要手动指回
console.log(new Student() instanceof Person); //true</span></pre>

Array.isArray()用于确定传递的值是否是一个 Array

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n131" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">// 下面的函数调用都返回 true
// 鲜为人知的事实:其实 Array.prototype 也是一个数组。
Array.isArray(Array.prototype); </pre>

constructor: 返回的是boolean类型(可判断数组类型)

在W3C定义中的定义:constructor 属性返回对创建此对象的数组函数的引用

任何一个对象都有constructor属性,就是返回对象相对应的构造函数。

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n138" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var arr=[1,2,3];
console.log(arr.constructor==Array);</pre>

-------------------------------------以下不是原创-------------------------------------

较为严谨并且通用的方法:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n145" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">function isArray(object){
return object && typeof object==='object' &&
Array == object.constructor;
}</pre>

!!注意:

使用instaceof和construcor,被判断的array必须是在当前页面声明的!比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),在子页面中声明了一个array,并将其赋值给父页面的一个变量,这时判断该变量,Array == object.constructor;会返回false;原因:1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array;切记,不然很难跟踪问题!

http://www.cnblogs.com/mofish/p/3388427.html

https://blog.csdn.net/zhangw428/article/details/4171630

https://my.oschina.net/sfm/blog/33197

https://www.cnblogs.com/onepixel/p/5126046.html(最详细)

dom节点获取,及其特性

1. 通过顶层document节点获取:

(1) document.getElementById(elementId):该方法通过节点的ID,可以准确获得需要的元素,是比较简单快捷的方法。如果页面上含有多个相同id的节点,那么只返回第一个节点。 如今,已经出现了如prototypeMootools等多个JavaScript库,它们提供了更简便的方法:<svg xmlns:xlink="http://www.w3.org/1999/xlink" width="98.161ex" height="2.759ex" viewBox="0 -863.1 42263.7 1188" role="img" focusable="false" style="vertical-align: -0.755ex;" class="in-text-selection"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)"><g transform="translate(1646,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">,</text></g><g transform="translate(2506,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">参</text></g><g transform="translate(3402,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">数</text></g><g transform="translate(4358,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">仍</text></g><g transform="translate(5279,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">然</text></g><g transform="translate(6235,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">是</text></g><g transform="translate(7191,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">节</text></g><g transform="translate(8112,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">点</text></g><g transform="translate(9033,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">的</text></g><g transform="translate(10761,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">。</text></g><g transform="translate(11622,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">这</text></g><g transform="translate(12578,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">个</text></g><g transform="translate(13534,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">方</text></g><g transform="translate(14455,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">法</text></g><g transform="translate(15411,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">可</text></g><g transform="translate(16271,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">以</text></g><g transform="translate(17167,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">看</text></g><g transform="translate(18124,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">作</text></g><g transform="translate(19080,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">是</text></g><g transform="translate(33000,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">的</text></g><g transform="translate(33860,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">另</text></g><g transform="translate(34781,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">外</text></g><g transform="translate(35737,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">一</text></g><g transform="translate(36693,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">种</text></g><g transform="translate(37614,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">写</text></g><g transform="translate(38535,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">法</text></g><g transform="translate(39491,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">,</text></g><g transform="translate(40351,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">不</text></g><g transform="translate(41307,0)"><text font-family="STIXGeneral,'Arial Unicode MS',serif" stroke="none" transform="scale(53.819) matrix(1 0 0 -1 0 0)">过</text></g></g></svg>​()的功能更为强大,具体用法可以参考它们各自的API文档。

(2)document.getElementsByName(elementName):该方法是通过节点的name获取节点,从名字可以看出,这个方法返回的不是一个节点元素,而是具有同样名称的节点数组。然后,我们可以通过要获取节点的某个属性来循环判断是否为需要的节点。 例如:在HTML中checkbox和radio都是通过相同的name属性值,来标识一个组内的元素。如果我们现在要获取被选中的元素,首先获取改组元素,然后循环判断是节点的checked属性值是否为true即可。

(3)document.getElementsByTagName(tagName):该方法是通过节点的Tag获取节点,同样该方法也是返回一个数组,例如:document.getElementsByTagName('A')将会返回页面上所有超链接节点。在获取节点之前,一般都是知道节点的类型的,所以使用该方法比较简单。但是缺点也是显而易见,那就是返回的数组可能十分庞大,这样就会浪费很多时间。那么,这个方法是不是就没有用处了呢?当然不是,这个方法和上面的两个不同,它不是document节点的专有方法,还可以应用其他的节点,下面将会提到。

2、通过父节点获取:

(1)parentObj.firstChild:如果节点为已知节点(parentObj)的第一个子节点就可以使用这个方法。这个属性是可以递归使用的,也就是支持parentObj.firstChild.firstChild.firstChild...的形式,如此就可以获得更深层次的节点。

(2)parentObj.lastChild:很显然,这个属性是获取已知节点(parentObj)的最后一个子节点。与firstChild一样,它也可以递归使用。 在使用中,如果我们把二者结合起来,那么将会达到更加令人兴奋的效果,即:parentObj.firstChild.lastChild.lastChild...

(3)parentObj.childNodes:获取已知节点的子节点数组,然后可以通过循环或者索引找到需要的节点。 注意:经测试发现,在IE7上获取的是直接子节点的数组,而在Firefox2.0.0.11上获取的是所有子节点即包括子节点的子节点。

(4)parentObj.children:获取已知节点的直接子节点数组。 注意:经测试,在IE7上,和childNodes效果一样,而Firefox2.0.0.11不支持。这也是为什么我要使用和其他方法不同样式的原因。因此不建议使用。

(5)parentObj.getElementsByTagName(tagName):使用方法不再赘述,它返回已知节点的所有子节点中类型为指定值的子节点数组。例如:parentObj.getElementsByTagName('A')返回已知的子节点中的所有超链接。 3、通过临近节点获取:

(1)neighbourNode.previousSibling:获取已知节点(neighbourNode)的前一个节点,这个属性和前面的firstChild、lastChild一样都似乎可以递归使用的。

(2)neighbourNode.nextSibling:获取已知节点(neighbourNode)的下一个节点,同样支持递归。

4、通过子节点获取:

(1)childNode.parentNode:获取已知节点的父节点。 上面提到的方法,只是一些基本的方法,如果使用了Prototype等JavaScript库,可能还获得其他不同的方法,例如通过节点的class获取等等。不过,如果能够灵活运用上面的各种方法,相信应该可以应付大部分的程序。


诊断内存泄漏的一个重要步骤是判断页面的DOM数量的增长情况,因此我们需要持续获取页面的DOM数量,方法如下:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n193" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">// 递归函数
function countNodes(node) {
// 计算自身
var count = 1;
// 判断是否存在子节点
if(node.hasChildNodes()) {
// 获取子节点
var cnodes = node.childNodes;
// 对子节点进行递归统计
for(var i=0; i<cnodes.length; i++) {
count = count + countNodes(cnodes.item(i))
}
}
return count;
}
// 统计body的节点数量
countNodes(document.body)1234567891011121314151617</pre>

将上面的代码周期执行,我们就可以发现页面节点增长是否在正确的范围内,节点的销毁是否正常。

https://blog.csdn.net/yiifaa/article/details/70048860


innerHTML与innerText区别

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n200" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="html" contenteditable="false"><html>
<head><title>innerHTML</title></head>
<body>
<div id="d1"><p id="p1">hello world </p></div>
<script>
var content = document.getElementById("d1");
alert(content.innerHTML);
alert(content.innerText)
</script>
</body>
</html></pre>

innerHTML指的是从对象的起始位置到终止位置的全部内容,包括Html标签innerText 指的是从起始位置到终止位置的内容,但它去除Html标签

https://blog.csdn.net/magi1201/article/details/44131361

1.innerText是id为object的闭合标签内的文本,输入输出的是转义文本(字符串); (label控件用innerText有效)

2.innerHtml是<div>标签内的文本,输入输出到该DOM内部纯HTML代码(流); (获得td、div等html元素时候,它们是没有value或是text属性,只能用innerHtml)

https://blog.csdn.net/maxracer/article/details/8750597

数组中的每个值至多出现1次的处理方法

https://github.com/mqyqingfeng/Blog/issues/27

https://blog.csdn.net/yangkai_hudong/article/details/22858723

伪数组和数组

伪数组

定义:

1、拥有length属性,其它属性(索引)为非负整数(对象中的索引会被当做字符串来处理,这里你可以当做是个非负整数串来理解)2、不具有数组所具有的方法

常见的参数的参数 arguments,DOM 对象列表(比如通过 document.getElementsByTags 得到的列表),jQuery 对象(比如 $("div"))。

伪数组是一个 Object,而真实的数组是一个 Array

《javascript权威指南》上给出了代码用来判断一个对象是否属于“类数组”。如下:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n227" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">// Determine if o is an array-like object.
// Strings and functions have numeric length properties, but are
// excluded by the typeof test. In client-side JavaScript, DOM text
// nodes have a numeric length property, and may need to be excluded
// with an additional o.nodeType != 3 test.
function isArrayLike(o) {
if (o && // o is not null, undefined, etc.
typeof o === 'object' && // o is an object
isFinite(o.length) && // o.length is a finite number
o.length >= 0 && // o.length is non-negative
o.length===Math.floor(o.length) && // o.length is an integer
o.length < 4294967296) // o.length < 2^32
return true; // Then o is array-like
else
return false; // Otherwise it is not
}</pre>

不过有个更简单的办法来判断,用 Array.isArray

JavaScript内置对象中常见的伪数组就是大名鼎鼎的auguments,除了length属性和索引元素之外没有任何Array属性。例如,它没有 pop 方法。但是它可以被转换为一个真正的Array

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n232" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var args = Array.prototype.slice.call(arguments);
var args = [].slice.call(arguments);

// ES2015
const args = Array.from(arguments);</pre>

在DOM对象中,childNodes也是伪数组

https://www.cnblogs.com/chenpingzhao/p/4764791.html

各种原生方法

https://linzx1993.github.io/2017/09/03/Javascripts%E6%95%B0%E7%BB%84%E5%8E%9F%E7%94%9F%E6%96%B9%E6%B3%95%E9%9B%86%E5%90%88/

html、dom0、dom2是如何注册事件

DOM0级方法指定的事件处理程序被认为是元素的方法,就是将一个函数赋值给一个事件处理程序属性(每个元素包括window和document都有自己处理程序的属性)。例如:onclick、onmouseover、onmouseout等。因此,这时候的事件处理程序是在元素的作用域中执行的;

’DOM2级事件’定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和removeEventListener();所有的DOM节点都包含这两种方法。 它们都接受3个参数:要处理的事件名,事件处理程序的函数,和一个布尔值。 最后一个参数:如果为true,表示在捕获阶段调用事件处理程序,如果是false,表示在冒泡阶段调用事件处理程序。

事件流

image

IE的事件流是冒泡, 从里面往上面冒, netscape是从外部元素往内部元素捕获; 而DOM2级的事件规定了事件流包含三个阶段包括: 1:事件捕获, 2:处于目标阶段, 3:事件

冒泡阶段(IE8以及更早版本不支持DOM事件流);

[图片上传失败...(image-69cff2-1528380772774)]

http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html

https://segmentfault.com/a/1190000004463384

http://www.cnblogs.com/yexiaochai/p/3567597.html(看不懂)

事件委托(代理)

https://www.cnblogs.com/owenChen/archive/2013/02/18/2915521.html

https://zhuanlan.zhihu.com/p/26536815

https://github.com/yonyouyc/blog/issues/25

异步同步

ajax

请求接口跨域了怎么解决

JSONP

https://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

浏览器同源政策及其规避方法http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

跨域资源共享 CORS 详解http://www.ruanyifeng.com/blog/2016/04/cors.html

ajax跨域,这应该是最全的解决方案了https://dailc.github.io/2017/03/22/ajaxCrossDomainSolution.html

变量声明提升(有可能有个题)

MDN变量提升https://developer.mozilla.org/zh-CN/docs/Glossary/Hoisting

https://blog.csdn.net/qq673318522/article/details/50810650

函数声明提升

1、函数的两种创建方式

  • 函数声明

  • 函数表达式

函数声明语法

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n298" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">f('superman');
function f(name){
console.log(name);
}1234</pre>

运行上面的程序,控制台能打印出supemran函数表达式语法

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n302" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">f('superman');
var f= function(name){
console.log(name);
}1234</pre>

运行上面的代码,会报错Uncaught ReferenceError: f is not defined(…),错误信息显示说f没有被定义。 为什么同样的代码,函数声明和函数表达式存在着差异呢? 这是因为,函数声明有一个非常重要的特征:函数声明提升,函数声明语句将会被提升到外部脚本或者外部函数作用域的顶部(是不是跟变量提升非常类似)。正是因为这个特征,所以可以把函数声明放在调用它的语句后面。如下面例子,最终的输出结果应该是什么?:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n307" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">var getName = function(){
console.log(2);
}
function getName (){
console.log(1);
}
getName();1234567</pre>

可能会有人觉得最后输出的结果是1。让我们来分析一下,这个例子涉及到了变量声明提升函数声明提升。正如前面说到的函数声明提升,函数声明function getName(){}的声明会被提前到顶部。而函数表达式var getName = function(){}则表现出变量声明提升。因此在这种情况下,getName也是一个变量,因此这个变量的声明也将提升到底部,而变量的赋值依然保留在原来的位置。需要注意的是,函数优先,虽然函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。因此上面的函数可以转换成下面的样子:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n310" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">function getName(){ //函数声明提升到顶部
console.log(1);
}
var getName; //变量声明提升
getName = function(){ //变量赋值依然保留在原来的位置
console.log(2);
}
getName(); // 最终输出:212345678</pre>

所以最终的输出结果是:2。在原来的例子中,函数声明虽然是在函数表达式后面,但由于函数声明提升到顶部,因此后面getName又被函数表达式的赋值操作给覆盖了,所以输出2。函数声明提升

1、函数的两种创建方式

  • 函数声明

  • 函数表达式

函数声明语法

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n323" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">f('superman');
function f(name){
console.log(name);
}1234</pre>

运行上面的程序,控制台能打印出supemran函数表达式语法

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n327" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false">f('superman');
var f= function(name){
console.log(name);
}1234</pre>

运行上面的代码,会报错Uncaught ReferenceError: f is not defined(…),错误信息显示说f没有被定义。 为什么同样的代码,函数声明和函数表达式存在着差异呢? 这是因为,函数声明有一个非常重要的特征:函数声明提升,函数声明语句将会被提升到外部脚本或者外部函数作用域的顶部(是不是跟变量提升非常类似)。正是因为这个特征,所以可以把函数声明放在调用它的语句后面。如下面例子,最终的输出结果应该是什么?:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n332" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var getName = function(){
console.log(2);
}
function getName (){
console.log(1);
}
getName();1234567</pre>

可能会有人觉得最后输出的结果是1。让我们来分析一下,这个例子涉及到了变量声明提升函数声明提升。正如前面说到的函数声明提升,函数声明function getName(){}的声明会被提前到顶部。而函数表达式var getName = function(){}则表现出变量声明提升。因此在这种情况下,getName也是一个变量,因此这个变量的声明也将提升到底部,而变量的赋值依然保留在原来的位置。需要注意的是,函数优先,虽然函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。因此上面的函数可以转换成下面的样子:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n335" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function getName(){ //函数声明提升到顶部
console.log(1);
}
var getName; //变量声明提升
getName = function(){ //变量赋值依然保留在原来的位置
console.log(2);
}
getName(); // 最终输出:212345678</pre>

所以最终的输出结果是:2。在原来的例子中,函数声明虽然是在函数表达式后面,但由于函数声明提升到顶部,因此后面getName又被函数表达式的赋值操作给覆盖了,所以输出2


<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n339" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var v='Hello World';
(function(){
alert(v);
var v='I love you';
})()
//undefined</pre>

实际上变成了

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n342" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">var v='Hello World';
(function(){
var v;
alert(v);
v='I love you';
})()</pre>

在我们写js code 的时候,我们有2中写法,一种是函数表达式,另外一种是函数声明方式。我们需要重点注意的是,只有函数声明形式才能被提升。

http://www.cnblogs.com/betarabbit/archive/2012/01/28/2330446.html

坚持在函数顶端声明变量

https://dancon.gitbooks.io/git-books/content/js/essay/function_hoisting.html

作用域

https://msdn.microsoft.com/zh-cn/library/bzt2dkta(v=vs.94).aspx

JavaScript 有两个范围:全局和局部。 在函数定义之外声明的变量是全局变量,它的值可在整个程序中访问和修改。 在函数定义内声明的变量是局部变量。 每当执行函数时,都会创建和销毁该变量,且无法通过函数之外的任何代码访问该变量。 JavaScript 不支持块范围(通过一组大括号 {. . .} 定义新范围),但块范围变量的特殊情况除外。

let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。

const常量是块级作用域,很像使用 let 语句定义的变量。常量的值不能通过重新赋值来改变,并且不能重新声明。


变量作用域与解构赋值

https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014344993159773a464f34e1724700a6d5dd9e235ceb7c000


http://www.cnblogs.com/rainman/archive/2009/04/28/1445687.html

4、函数中声明的变量在整个函数中都有定义。

首先观察这段代码:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n370" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="" contenteditable="false"><script type="text/javascript">
function rain(){
var x = 1;
function man(){
x = 100;
}
man(); //调用man
alert( x ); //这里会弹出 100
}
rain(); //调用rain
</script></pre>

上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。由于这条规则,会产生“匪夷所思”的结果,观察下面的代码。

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n373" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false"><script type="text/javascript">
var x = 1;
function rain(){
alert( x ); //弹出 'undefined',而不是1
var x = 'rain-man';
alert( x ); //弹出 'rain-man'
}
rain();
</script></pre>

是由于在函数rain内局部变量x在整个函数体内都有定义( var x= 'rain-man',进行了声明),所以在整个rain函数体内隐藏了同名的全局变量x。这里之所以会弹出'undefined'是因为,第一个执行alert(x)时,局部变量x仍未被初始化。

所以上面的rain函数等同于下面的函数:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n378" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function rain(){
var x;
alert( x );
x = 'rain-man';
alert( x );
}</pre>


函数声明比变量声明优先级高

克隆对象

深拷贝和浅拷贝

https://www.zhihu.com/question/23031215

this

深入理解JS中声明提升、作用域(链)和this关键字

https://github.com/creeperyang/blog/issues/16

this

this关键词是JavaScript中最令人疑惑的机制之一。this是非常特殊的关键词标识符,在每个函数的作用域中被自动创建,但它到底指向什么(对象),很多人弄不清。

当函数被调用,一个activation record(即 execution context)被创建。这个record包涵信息:函数在哪调用(call-stack),函数怎么调用的,参数等等。record的一个属性就是this,指向函数执行期间的this对象。

  • this不是author-time binding,而是 runtime binding。

  • this的上下文基于函数调用的情况。和函数在哪定义无关,而和函数怎么调用有关。

修改this指向的方法

call()与apply()区别

一、方法的定义 call方法: 语法:call(thisObj,Object)定义:调用一个对象的一个方法,以另一个对象替换当前对象。说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 apply方法: 语法:apply(thisObj,[argArray])定义:应用某一对象的一个方法,用另一个对象替换当前对象。 说明: 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。


bind方法

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了bind的第一个参数,无论这个函数是如何被调用的。

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n424" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function f(){
return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

var h = g.bind({a:'yoo'}); // bind只生效一次!
console.log(h()); // azerty

var o = {a:37, f:f, g:g, h:h};
console.log(o.f(), o.g(), o.h()); // 37, azerty, azerty</pre>


JavaScript中,有一个十分常用且不空忽视的关键字——this。虽然它仅仅由四个字母组成,但是却不简单。随着函数使用场合的不同,this的指向也会跟着发生相应的变化,正是因为这一特性让很多初学者拿不下JS中的这块“硬骨头”。

在JS中,this一般指向的是当前被调用者,但也可以通过其它方式来改变this指向。常见的函数调用有如下几种:函数名加括号调用、事件驱动式调用、new的方式调用。

今天,笔者就来详谈一下可以改变this指向的三种方式:call、apply、bind。

call(thisObj[, arg1[, arg2[, ...]]])

定义:使用一个指定的thisObj和若干个指定的参数值的前提下调用某个函数或方法;通过call方法,你可以在一个对象上借用另一个对象上的方法。

语法:fn.call(thisObj[, arg1[, arg2[, ...]]])

注意:

1、使用call的时候,thisObj不传或者为null、undefined时,函数中的this会指向window对象。

2、传递一个别的函数名时,函数中的this将指向这个函数的引用。

3、传递的值为数字、布尔值、字符串,this会指向这些基本类型的包装对象Number、Boolean、String。

4、传递一个对象,函数中的this则被“修正”为传递的这个对象。

apply(thisObj[,argArray])

定义:使用一个指定的thisObj和一个包含多个参数的数组或类数组对象的前提下调用某个函数或方法

比较apply和call的定义,我们发现这两者貌似没有多大差别。事实上它们的区别主要体现在第二个参数上。

注意:如果argArray不是一个有效的数组或者不是arguments对象,那么将导致一个TypeError。如果在调用的时候不提供任何参数,那么window对象将自动做为默认值。

bind()

定义:创建一个函数的实例,其this值会被绑定到传给bind()函数的值

在ES5中还提供了一个叫bind的函数,这个相对简单一些。bind方法允许手动传入一个this作为当前方法的上下文,然后返回持有上下文的方法。

当我们需要修正this时,只需要在花括号外面在调用一下bind并将要修正的对象传进去即可。

注意:bind与call和apply的不同点在于:bind不会执行对应的函数,call或apply会自动执行对应的函数


改变this的指向

1.用new调用函数,改变指向new的实例对象

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n471" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function fn(){
console.log(this);
}
let a=new fn();
//输出 {}(指向对象a)</pre>

2.bind

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n475" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function fn(){
console.log(this.name);
};
var obj={
name:'jack',
};
var b=fn.bind(obj);
b();</pre>

3.call

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n479" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function fn(name){
this.name=name;
this.fn1=function(){
console.log(this.name);
}
};
var obj={};
fn.call(obj,'jack');
console.log(obj.name);
obj.fn1();</pre>

4.apply

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n483" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function fn(name,age){
this.name=name;
this.age=age;
this.fn1=function(){
console.log(this.name);
}
};
var obj={};
fn.apply(obj,['jack',18]);
console.log(obj.age);
obj.fn1();</pre>

柯里化

JS 函数式编程指南

https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/ch4.html#%E6%80%BB%E7%BB%93

curry 的概念很简单:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。


柯里化和柯南的关系是?

http://www.zhangxinxu.com/wordpress/2013/02/js-currying/

① 柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

闭包

闭包(closure)

A closure is the combination of a function and the lexical environment within which that function was declared.

在 JavaScript 中,函数形成闭包。闭包就是函数和函数声明时的词法作用域的组合。(函数和函数声明时的词法作用域形成闭包 )

下面用例子说明:

<pre spellcheck="false" class="md-fences md-end-block contain-cm modeLoaded" cid="n506" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9rem; white-space: normal; --select-text-font-color: #fff; line-height: 1.71429em; display: block; break-inside: avoid; text-align: left; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(218, 218, 218); position: relative !important; margin-bottom: 3em; padding-left: 1ch; padding-right: 1ch; margin-left: 2em; width: inherit; color: rgb(31, 9, 9); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" lang="javascript" contenteditable="false">function outer () {
var name = 'Jerry'
function inner () {
console.log(name)
}
return inner
}

var fn = outer()
fn() // Jerry</pre>

在部分编程语言中,函数内部的局部变量仅仅存在于函数执行期间,一旦函数执行完毕,变量就销毁(不再能访问)。

但在 JavaScript 中,由于闭包的原因,fn 仍可以访问 name 变量。

https://github.com/creeperyang/blog/issues/16

js运行机制

http://www.ruanyifeng.com/blog/2014/10/event-loop.html

  • 单线程

  • 任务队列

    同步任务(synchronous),另一种是异步任务(asynchronous)

  • 事件和回调函数

  • Event Loop

  • 定时器


image

https://juejin.im/post/59e85eebf265da430d571f89

原型链

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

对象的继承机制

load/domContentLoaded事件、异步/延迟Js 与DOM解析

JavaScript深入之词法作用域和动态作用域https://github.com/mqyqingfeng/Blog/issues/3

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容