【经验】JavaScript

1.
function closeWin(){         
    window.open('','_self');   
    window.opener=null;  
//    window.open(location, '_self').close();
    window.close();      
}
这段是兼容最新浏览器的关闭窗口代码,但是在chrome下以输入网址打开的页面无法使用window.close(),会提示Scripts may close only the windows that were opened by it.

2.为input元素添加属性autocomplete="off" ,可以阻止火狐对input元素的缓存。据说type="hidden"的input会遇到这个问题。
3.
var a = {f:function f(){}};
console.log(a.f);//f()
console.log(f);//ReferenceError: f is not defined
4.依赖注入有两种实现,一种以f.toString方法获取函数字符串,这种在代码压缩时有缺陷,另一种以显式注入获取参数。
5.angularJS的作用域与DOM的关联是:作用域的层级由DOM的层级决定。
6.frameElement、frameDocument是非法变量名
7.HTML中的文本会包含"\n"," ","\t"等,每个算一个字符长度,如果用console的话会被转换,然后显示到控制台中。

8.(function(){}());var fn = function(){}()为何不报错而function(){}()会报错?
先说结论与其推导:
(1)function(){}()的报错是function statement requires a name
(2)function f(){}()的报错是expected expression, got ')'
(3)()的报错是expected expression, got ')'
这三个证据指明一个结论:function(){}()会被执行为function(){};();
原因应该是:以"function"关键字开头的语句,会被视为函数声明


【观点1:是{}没有被正确理解】
http://blog.csdn.net/woshinia/article/details/18666223
function(){}() //匿名函数立即执行, 语法分析期报错
{}.constructor //获取对象直接量的构造器,语法分析期报错
令人不解的是为何[].constructor这么写却不报错呢,一个是想获取对象直接量的构造器,一个是获取数组直接量的构造器而已。
当然添加个变量接收也不会报错
var c = {}.constructor;
var fn = function(){}(),也不会报错。
实际上是js的“语句优先”在作怪,即{}被理解成复合语句块而不是对象直接量或声明函数的语义。
【但是,我的测试结果并不支持这个说法,如下】
function f(){}()//Firebug报错SyntaxError: expected expression, got ')'
function a(){};();//报错同上
();//报错同上,这可能是括号被理解为“表达式分组”,而不是“函数调用”。并不是大括号的问题。
【我觉得原因是是第二对()没有被正确理解】
【但是http://www.cnblogs.com/snandy/archive/2011/03/08/1977112.html的评论里还是支持观点1】

http://www.zhcexo.com/round-brackets-in-javascript/
//例3
(function () {
    //...
})();

//例4
(function () {
    //...
}());

例3其实是强制运算圆括号中的函数,运算的结果是返回了函数自身,后面的括号就是函数的调用运算符,去调用被强制运算了的函数。
而例4,圆括号的强制运算使得函数的调用运算得以执行,然后返回的是调用结果。虽然都能让函数调用起作用,但其实背后的原理就有这种小区别。
//例5
void function () {  
    //...
}();

//例6
~function () {
    //...
}();
void 和 ~ 都是一元运算符,它们的运算优先级都是低于最后面的括号的,但是 js 在解析的过程中,遇到了 void 和 ~,就会把后面的匿名函数识别为操作数,而它们的计算优先级比圆括号低,所以就发生了函数的调用,调用的结果再进行 void 和 ~ 运算,返回 undefined 和 -1。
还有-,+,!,或者2*funct...}()。恐怕都是把匿名函数视为操作数,同理(function(){}())也应该是同样道理。
10.javascript有get和set访问器,不知道为何从未看到过。
data = 1;
var o = {
  data : 2,
  get data(){
    console.log('获取data数据');
    return data;
  },
  set data(value){
    console.log('设置data数据');
    data = value;
    console.log(this.data);
  }
}
o.data = 99;//data与o.data都会变成99
如果打印o,o的data属性仍显示1,而不是2

11.
http://www.cnblogs.com/snandy/archive/2011/03/08/1977112.html#comment_anchor_2042145

void操作符会触发其后表达式的GetValue(也就是get访问器)。分组运算符() 同 delete typeof 等运算符类似. 不会对运算元.造成 GetValue()。
delete 玩笑; //不会抛出异常.
原因是运行时,执行到 delete 玩笑; 时, 并不会对标识符-玩笑,进行GetValue().

delete (玩笑);//同样不会抛出异常.
可见分组运算符() 并没有对 标识符 -玩笑 做额外的工作. 它仅仅是影响语法树的产生过程.


以上,根据《你不知道的js》上卷P8所言,void似乎是触发了所谓的RHS查询,delete触发了LHS查询(RHS查询容器的值,LHS查询容器本身)

12.FF上在setTimeout计时中执行alert(),不会阻塞计时器;在chrome和ie11上,退出alert后会继续计时。
13.delete数组元素会用undefined填充,所以用[].splice吧
14.p不能包含div,如果p>div>img时用$('p img')会查不到元素
15. new Date(2015,0,1)的结果是1月1日。new Date(2015,0,0)的结果是2014年12月31日。
16.mouseleave和mouseenter是不会冒泡的mouseout、mouseover
17.
关于jQuery的event对象的target:
relatedTarget是指与在mouseover/enter、mouseout/leave时,鼠标将从中进入监听事件的元素的元素、鼠标将从监听事件的元素内进入的元素。
currentTarget绑定事件处理函数的元素。
delegateTarget是指使用jq的事件委托时,受委托的父元素。当事件绑定没使用事件委托时,等于currentTarget。
target是指触发事件的元素。target可能是currentTarget也可能是currentTarget的子元素。

关于原生event对象:

target:触发事件的元素
currentTarget:绑定事件处理函数的元素
originalTarget:相当于target
explicitOriginalTarget:最原始的事件发生节点,有可能是文本节点

18.keypress与keydown和keyup无关。它监听字符输入,并以charCode或keyCode返回字符的Unicode值,如果按键为ctrl之类的不会触发keypress。
19.href用"/"分割,可以用string.split("/")分割。
20.导航栏跟随滚动的经验
第一次:使用fixed
发现fixed根据视口定位,这样left就会有问题,当页面有水平滚动时也会跟随滚动。
第二次:使用absolute+js
元素相对body绝对定位,滚动时使用jq的offset()设定其top。
问题在于ie和chrome下导航会出现原因不明的闪烁,并非性能问题。
第三次:使用fixed+js
元素采取fixed,滚动时使用jq的css()设定其left。
head.css({
  left: (-1 * scrollLeft || 'auto') + 'px'
})
当无水平滚动时使用auto,当有水平滚动时相对视口往左偏移滚动的数值。
21.$(document).scroll(function...)这在IE8无法监听滚动事件,应该改成$(window)
22.window.undefined是不可改变的,但函数内部可以定义undefined
23.比较浏览器视口与页面body的高度
(document.documentElement.clientHeight > document.body.clientHeight)
23.1 document.documentElement.scrollHeight === $(document).height()

24.声明一个空数组arr,设置arr[5] = undefined;
则arr.length === 6,使用for(var i in arr){console.log(i)},会只打印5
25.在callback中写this,好像会变成undefined
26.arguments不是数组,所以不能直接做arguments.slice()
得要Array.prototype.slice.call(arguments, 1)
27.var a;并不等同于var a = undefined;
function f(a){
  var a ;
  console.log(a)
}
f(0)//0
function f(a){
  var a = undefined ;
  console.log(a)
}
f(0)//undefined
优先执行顺序为:
var a;
a = arguments[0]
a = undefined;
27.1 那么对于外部变量的读取优先度又如何呢?
var data = 1;
function f(){
  var data = data;
  console.log(data)
}
f()//打印undefined。

var data = 1;
function f(data){
  var data = data;
  console.log(data)
}
f(data)//打印1。
说明外部变量的读取,还在a = arguments[0]之前;
【也有可能是,读data时会在作用域找,结果找到内部作用域的var a了,没能去到外部】


28.对a执行elem.click(),是不会触发其跳转功能的,必须给其加一个子元素,对子元素模拟点击。
29.事件绑定中的事件对象,
e.delegateTarget是被委托的父元素
e.currentTarget是目标子元素
e.target是触发事件的元素,即子元素或其子元素
30.JSON.parse('{"left": 1}'),注意其中一定要用双引号,$.parseJSON也是一样的。

31.都说for-in会遍历所有原型链上的属性,为什么对{}做遍历不能遍历到toString这些key?
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Object.defineProperty()

32.深拷贝使用还原字符串的实现有限制性:
var o = {
 a: 1,
 b: 2,
 sum: function() { return a + b; }
};
var o2 = JSON.parse(JSON.stringify(o));//Object {a: 1, b: 2}
似乎是无法复制方法的意思

而且在继承上有问题:
JSON.parse(JSON.stringify(new A())) instanceof A === false

33.我认为,所有构造函数必须拥有函数名,以便于使用o.constructor查看其实例o的构造器。
34.onblur事件可以在body上触发(点一下body,再点一下body所处的frame之外的页面。点网页外面是无效的,点frame内body外的区域也是无效)。
如果写<body onblur="">,和onclick不同,在input里触发的onblur是不会触发这个事件处理函数的(毕竟click也点到了body,而焦点并没有离开body);
34.1 使用jq的话,虽然div元素无法触发blur事件,但是可以为其中的input做blur的事件委托。
34.1.1 blur事件无法做事件传播,事件委托的原理是检查
35. var a = function f(){};console.log(f)//f is not defined
f居然会成为私有变量
36.大括号"{"不能作为表达式开头
http://www.cnblogs.com/ziyunfei/archive/2012/09/16/2687589.html
{} == true//expected expression, got '=='
true == {}//无报错
36.1 {a:2}中的大括号会被认为是代码块,a:2是正确的语法,但我不明白是做什么用
37.'0' == false; 但('0' && 9)会通过并返回9。
http://www.cnblogs.com/mofish/p/3402407.html
原因是==的规则,如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
38.无论是ng或者其他,当一个元素会被重用时,应该off掉其上相应的事件监听
39.keypress在ff下可以由方向键触发,在IE和chrome下不行。
40.function f(a, b){a = 2, b = 2;console.log(arguments)};
f();//打印空数组
f(3);//打印[2]
f(3,3);//打印[2,2]
是说,当参数为空时,对参数的修改不会影响到arguments对象。
41.如果函数a返回了函数引用(包括返回对象,对象具有在函数中定义的方法),那得注意a在返回时,其内部是否有废弃数据(比如运算的中间缓存)。若有,则将之置为null。
当然尽可能地在运算中不产生废弃数据是未雨绸缪。
另外,尽可能在函数中使用匿即调封装作用域,不让返回的函数能访问到不必要的数据。
42.只有undefined==null
43.js的date,date是从1到31。month和day都是从0开始。
44. Function是它本身的构造器
44.1 Function的原型的类型是"function",却又不继承自Function,其构造器直接是Object
var p = Function.__proto__
typeof p === 'function' // true 这个应该是有问题的
p instanceof Function // false
p === Object.prototype // true
45.for (var i in obj){ obj = {} }
for会暂存对初始obj的引用,改变obj变量的指向,并不会中断遍历
46. typeof asd 在asd未定义时不会报错
47.使用var a = 1声明的变量,使用delete window.a返回false,不使用var而直接赋值一个变量b = 2,这个隐式全局变量将可以通过delete window.b删除,结果返回true
48. Function与eval的区别
Function只能访问全局作用域,其所处作用域的变量无法在其中访问到。
而eval是在当前作用域执行的。
49.变量对象(简称VO)不包括arguments,是一个抽象概念。活动对象(简称AO)是一个实体,它在函数被执行时产生,包括arguments。
变量对象的属性应该包括指向父级活动对象的__parent__,因为这个在编译期就可以决定,而且全局对象中也存在__parent__(指向null)。
this不是变量对象的属性,也不是活动对象的属性——this与它同辈,是执行上下文的属性。(执行上下文,包含变量对象(我认为这里是活动对象)、作用域链、this)
作用域链连接的是变量对象。
全局中貌似不存在活动对象。
50.数组里存放undefined与默认生成undefined还是有区别的
function keepUndefined(v){return v === undefined}
var arr1 = []; arr1[2] = 1; var arr2 = [undefined, undefined, 1];
console.log(arr1.filter(keepUndefined));// []
console.log(arr2.filter(keepUndefined));// [undefined, undefined]
// 而map比较奇怪,实际上"0" in arr1 的结果是false,它依旧会返回三个值。而实际上并没有遍历到arr1[0]和arr1[1],如果keepUndefined里打印只会打印一次。
// arr1 = new Array(3);arr1[0] = 1;同理,结果是[false,u,u]
console.log(arr1.map(keepUndefined));// [undefined, undefined, false]
51. [0]参与运算的结果有以下几种情况
+[0] // 0,数字
0+[0] // "00",字符串
0-[0] // 0,数字
if([0])[] // 通过
[0] == 0 // true
[0] === 0 // false
52. 1 + - + + + - + 1 这个式子应该被理解为1+(...1),后面的加减是正负号。
53.arguments和形参是相关联的。
54. js里大数和小数运算会有精确度问题
var a = 111111111111111110000,
    b = 111111;
a + b; // 111111111111111230000 千位及后面被向上舍去
55.关于valueOf和toString的优先度:
https://zhidao.baidu.com/question/1928417783204179667.html
valueOf偏向于运算,toString偏向于显示。
1、 在进行对象转换时(例如:alert(a)),将优先调用toString方法,如若没有重写toString将调用valueOf方法,如果两方法都不没有重写,但按Object的toString输出。
2、 在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
3、 在有运算操作符的情况下,valueOf的优先级高于toString。

document.write({toString: function(){return 1}, valueOf: function(){return 10}})  // 1 这是第一种情况
1+{toString: function(){return 1}, valueOf: function(){return 10}} // 11 第二种情况

posted @ 2017-03-06 18:49  FranQ  阅读(180)  评论(0编辑  收藏  举报