zoukankan      html  css  js  c++  java
  • JavaScript必知必会+理解总结

    这是stackoverflow上的一个老问题,却有个干货答案,但是扩展的信息量很大,我只在此抛个砖。
    Not jQuery. Not YUI. Not 等等…
    js的框架的确很有用,但是它们却常常把一些js的丑陋细节和DOM原理给你隐藏了。如果你的目标是做一个精通JavaScript的工程师,那花大把的时间放在框架上可能恰恰背道而驰了。
    下面就有javascript这门语言的一些特性,你应该知道并且深谙此道,但是很多人可能还并不清楚。


    一、对象属性,object.prop和object['prop']是一回事(所以你能停止使用eval了吗?!3KU);对象的属性多是String类型(有些也是数组Array)

    for…in是什么情况下使用,什么情况慎用?
    方括号可以通过变量来访问属性
    1. person.name;
    2. person['name'];
    3. var propertyName = 'name';
    4. person[propertyName]; // name
    复制代码
    当属性是带空格的string时就只能用方括号了:person['first name'];
    for…in 循环输出的属性名顺序不可预测,使用之前先检测对象是否为null 或者 undefined
    二、属性检测;undefined和null;为什么鲜为人知的in运算符非常有用,以及它和typeof、undefined的区别;hasOwnProperty;delete作用
    undefined好理解一般用来表示未定义,而且不能用delete来删除它。
    null 表示一个空对象指针 所以 typeof null返回 object
    undefined派生自null alert(null == undefined) 返回true; 但alert(null === undefined)就返回false了

    关于hasOwnProperty和Object:

    hasOwnProperty是js中唯一一个处理属性但是不查找原型链的函数
    1. Object.prototype.prop = 'propsss';
    2. var obj = {und:undefined};

    3. obj.prop; // propsss
    4. 'und' in obj; // true

    5. obj.hasOwnProperty('prop'); // false
    6. obj.hasOwnProperty('und'); // true
    7. //只有hasOwnProperty可以给出正确和期望的结果,尤其在遍历一个对象时
    8. //除了hasOwnProperty外,没有其他方法可以排除原型链上的属性(不是定义在对象自身上的属性)

    9. //如果hasOwnProperty被占用呢?来看:
    10. var obj = {
    11.     hasOwnProperty: function(){
    12.         return false;
    13.     },
    14.     prop: 'this is bad...'
    15. };
    16. obj.hasOwnProperty('prop'); // 总是返回false
    17. //这样解决:
    18. {}.hasOwnProperty.call(obj,'prop'); // 返回true
    复制代码
    var o =new Object();
    Object的每个实例都具有下列属性方法:
    1.Constructor:保存着用于创建当前对象的函数 上面例子 构造函数就是 Object()
    2.hasOwnProperty(prop):检查给定的属性是否在当前对象实例中(而不是在实例的原型中)。作为参数的属性必须以string形式指定
    3.isPrototypeOf(object):用于检查传入的对象是否是另一个对象的原型。
    4.propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for in语句
    5.toLocaleString():返回对象的字符串表示,与环境的地区对应
    6.toString():同上
    7.valueOf(): 返回对象的字符串、number、Boolean表示。通常与toString()相同


    三、Number类型就是浮点类型(64位浮点数);使用浮点数会遇到语言无关性的问题;避免使用parseInt时的八进制陷阱

    ECMAScript5不具有解析八进制的能力,可在IE7和chrome上测试 parseInt(069);
    ES3和ES5之间存在分歧
    javascript中的乘法问题:
    一般可以用 10000 作为基数
    31.12 * 10000 * 9.7 / 10000
    四、嵌套函数作用域;避免全局变量导致的意外而使用var的必要性;闭包的作用域如何结合使用;在循环与闭包的问题
    作用域和var关键字的面试题
    1. function(){
    2. var a=b=10;
    3. }
    4. console.log(a);
    5. console.log(b);
    复制代码
    循环中使用闭包
    1. function createFunctions(){
    2.     var result = new Array();
    3.     for(var i=0;i<10;i++){
    4.         result[i] = fucntion(){
    5.             return i;
    6.         }
    7.     }
    8.     return result;
    9. }
    10. //每个函数的作用域链中都保存着createFunctions()函数的活动对象,所以他们引用的都是同一个变量i。
    11. //当createFunctions()返回后 变量i的值是10
    12. //所以可以这样写
    13. for(var i=0;i<10;i++){  
    14.   result[i] = function(num){
    15.     return function(){  
    16.         return num;  
    17.     };  
    18.   }(i);  
    19. }
    复制代码
    之前写过的闭包的理解关于闭包


    五、全局变量和window对象的属性产生冲突怎么办(它们其实是一回事);全局变量和DOM元素在IE中的冲突;在全局作用域中使用var来避免这些问题

    六、 function语句在解析时会被提升(不管function被放置在哪里,它都会被移动到定义时所在作用域的顶层) 函数声明和函数表达式;为什么命名函数表达式不应该使用

    关于函数声明提升
    解析器会执行一个函数声明提升(function decalaration hoisting)的过程,读取并将函数声明添加到执行环境中。
    对代码求值时js引擎在第一遍会声明函数并将它们放到源代码树的顶部。
    1. alert(sum(10,10))
    2. function sum(n1,n2){
    3.     return n1+n2;
    4. }
    5. //单独使用下面代码时,函数表达式会出错:
    6. alert(sum(10,10));
    7. var sum = function (n1,n2){
    8.     return n1+n2;
    9. }
    复制代码
    关于命名函数表达式
    1、命名函数表达式即被认为是函数声明也被认为是函数表达式
    1. typeof g; // "function"
    2. var f = function g(){};
    3. //上面这个例子论证了 jScript 是如何把一个命名函数表达式处理成一个函数声明的
    4. //在函数声明发生之前就把 g 给解析了   【在IE中检测】
    复制代码
    2、命名函数表达式还能创建两个不同的函数对象—-这是js的bug
    1. var f = function g(){};
    2. f === g;  //false

    3. f.prop = 'a prop';
    4. g.prop; // undefined  【在IE中检测】
    复制代码
    竟然创建了两个对象,他们之间还不是引用的关系,是不是很有趣。。。我只能说:呵呵 interesting……


    3、在条件语句中命名函数表达的声明式仍然会被解析

    1. var f = function g(){
    2.     return 1;
    3. };
    4. if(false){
    5.     f= function g(){
    6.         return 100;
    7.     };
    8. }
    9. g(); //猜猜返回什么 【在IE中检测】

    10. //还有arguments也中枪了
    11. var f = function g(){
    12.     return [
    13.       arguments.callee == f,
    14.       arguments.callee == g
    15.     ];
    16.   };
    17. console.log(f()); // [true, false]
    18. console.log(g()); // [false, true]   【在IE中检测】
    复制代码
    注:上面的3条准确的说应该是算是jScript的bug


    七、构造函数;prototype属性;new运算符的运行机制;利用这些方法实现一个类-子类-实例的系统;在何时应该考虑使基于闭包的对象来替代原型设计

    八、this是在函数调用时才被确定的而不是定义的时候;把函数当做参数传入时不像其他语言那样执行;如何使用闭包或者Function.prototype.bind来解决这些问题呢
    关于this的调用,直接上代码:
    1. var Dog = {
    2.     toString: function() { return 'dog';},
    3.     fn: function() { alert(this);},
    4. };
    5. var Cat = {
    6.     toString: function() { return 'cat';}
    7. };

    8. Dog.fn(); // dog
    9. Dog['fn']() // dog

    10. Cat.fn = Dog.fn;
    11. Cat.fn(); // cat

    12. var func = Dog.fn;
    13. func(); // window
    复制代码
    上面代码很简单 请自行补脑……
    1. Obj.method = function() {
    2.     var self = this;
    3.     function test() {
    4.         //this 被设置为全局对象(window)
    5.         //self 指向 Obj 对象
    6.     }
    7. }

    8. //想到了arguments做个低耦合的递归求阶乘
    9. function factorial(num) {
    10.     if(num<=1)
    11.         return 1;
    12.     else
    13.         return num*arguments.callee(num-1);
    14. }
    15. //callee指向拥有这个arguments对象的函数
    复制代码
    关于Function.prototype.bind(thisArg [, arg1 [, arg2, …]]):
    这是ECMAScript 5中的方法看看Opera的对它的介绍吧


    简单翻译就是:

    Function.prototype.bind 返回一个新的函数对象,该对象的 this 绑定到了thisArg参数上。本质就是:这允许你在其他对象链中执行一个函数
    但是很多浏览器不支持,通过一个js的hack看看原理吧:
    1. if(!Object.bind){
    2.     Function.prototype.bind = function(owner){
    3.         var self = this;
    4.         var args = Array.prototype.slice.call(arguments,1);
    5.         return function() {
    6.             return self.allpy(
    7.                 args.length===0 ? arguments : arguments.length===0? args:
    8.                     args.contact(Array.prototype.slice.call(arguments,0))
    9.             );
    10.         };
    11.     };
    12. }
    复制代码
    九、其他的ES5新特性如indexOf  、 forEach 以及Array使用函数式编程;旧浏览器如何兼容这些新的方法;使用匿名函数调用这些方法来使代码更加紧致具有可读性
    1. Array.prototype.indexOf(searchString ,position)
    2.     var data = [1,3,5,7,9];
    3.     console.log(data.indexOf(5)); //2
    4.     console.log(data.indexOf(5,4)); //-1  从4号位开始搜索
    5.     console.log(data.indexOf('7'));  //-1  7!== '7'

    6. Array.prototype.lastIndexOf //从末尾开始查找
    7. Array.prototype.some //某些条件符合
    8.     var arr = [1,2,3,4,11];
    9.     function larger(item){
    10.         return item> 10   
    11.     }
    12.     console.log(arr.some(larger)?'ok':'no...');
    13.     //注:只要有一条符合 即返回true 不再执行

    14. Array.prototype.every // all符合  和some相比就是返回的 true 和 false 调换一下

    15. Array.prototype.forEach //类似jQ里的each
    16.     [1, 2 ,3, 4].forEach(alert);
    17.     [1, 2 ,3, 4].forEach(console.log);//FF下运行 不知为什么chrome不行。。。。。

    18. Array.prototype.map //映射 类似forEach 把原数组映射成新数组
    19.     var arr = [1,3,5,7];
    20.     var result = arr.map(function(item){
    21.         return item * item;
    22.     });
    23.     console.log(result); //求各项平方

    24. Array.prototype.filter //筛选
    25.     var filter = [0,2,3,0,undefined].filter(function(item){
    26.         return item;
    27.     });
    28.     console.log(filter);
    29.     //filter的callback函数需要返回值为 true 或 false。若为false则过滤掉

    30. Array.prototype.reduce //不是减少  是一种迭代
    31.     var sum = [1,2,3,4,5].reduce(function(pre,current,index,array) {
    32.         return pre + current;
    33.     });
    34. console.log(sum); //15

    35. Array.prototype.reduceRight //right 自然是从数组末未开始
    复制代码
    这些都是 ES5 中 Array 对象的扩展方法
    PS:还是点此自行补脑,我也在研究中…..后续会再补充
    十、浏览器和js代码之间控制流程的原理;同步和异步执行;事件在运行时触发和事件在控制返回时触发的区别;调用同步执行的方法如alert而引起控制流重新进入的潜在问题(翻译不通,请自行补脑)。
    十一、跨window脚本对instanceof的影响 在不同的DOM中跨window脚本对控制流的影响;postMessage怎么解决这个问题
    postMessage就是HTML5解决跨域问题引入的API,使得多个iframe/window实现跨域通信。
    最重要的是,你需要批判的去看待javascript,承认因为种种历史原因而导致各种不完美(甚至比其他语言还要糟糕),并要避免各种陷阱。Crockford在这方面的研究很值得学习(虽然我不完全认同他的《JavaScript语言精粹》)JavaScript必知必会+理解总结
  • 相关阅读:
    [android] 帧布局
    [android] 表格布局和绝对布局
    使用LVS实现负载均衡原理及安装配置详解
    学习Docker之Dockerfile的命令
    使用docker-compose部署nginx
    CentOS Bash 命令补全增强软件包 bash-completion
    “三次握手,四次挥手”你真的懂吗?
    0777 0的意思
    linux文件或目录权限修改后如何恢复(备份了权限就能恢复)
    centos7进入单用户模式
  • 原文地址:https://www.cnblogs.com/linaijiao/p/3501359.html
Copyright © 2011-2022 走看看