1、对象:

JS中所有的变量都是对象,除了两个例外 null和undefined .

一个常见的误解是数字的字面值(literal)不是对象。这是因为 JavaScript 解析器的一个错误, 它试图将点操作符解析为浮点数字面值的一部分。

ex: 2.toString()    //synaxError  原因是以为.是浮点数的点

转化方法:

2..toString(); // 第二个点号可以正常解析
2 .toString(); // 注意点号前面的空格
(2).toString(); // 2先被计算

有两种方式可以访问对象的属性,点操作符或者中括号操作符

var  s = { name : "h"}

s.name 和s["name"]均可以访问

但是中括号可以用于动态的访问,属性名中含有空格,属性名是JS关键字之类

删除属性唯一的方法是使用delete,设置属性为Null或者undefined并不能真正删除属性。仅仅是移除了属性和值的关联

2、Javascript原型链:

function Foo() {this.value = 42;
}
Foo.prototype = {method: function() {}
};function Bar() {}// 设置Bar的prototype属性为Foo的实例对象
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';// 修正Bar.prototype.constructor为Bar本身
Bar.prototype.constructor = Bar;var test = new Bar() // 创建Bar的一个新实例// 原型链
test [Bar的实例]Bar.prototype [Foo的实例] { foo: 'Hello World' }Foo.prototype{method: ...};Object.prototype{toString: ... /* etc. */};

上面的例子中, test 对象从  Bar.prototype 和  Foo.prototype 继承下来;因此, 它能访问  Foo 的原型方法  method。同时,它也能够访问 那个定义在原型上的  Foo 实例属性  value。 需要注意的是  new Bar()  不会创造出一个新的  Foo 实例,而是 重复使用它原型上的那个实例;因此,所有的  Bar 实例都会共享 相同的  value 属性。

当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止。

如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。

并且,当使用 for in 循环遍历对象的属性时,原型链上的所有属性都将被访问。

所以:

在写复杂的 JavaScript 应用之前,充分理解原型链继承的工作方式是每个 JavaScript 程序员必修的功课。 要提防原型链过长带来的性能问题,并知道如何通过缩短原型链来提高性能。 更进一步,绝对不要扩展内置类型的原型,除非是为了和新的 JavaScript 引擎兼容。

for in循环

和 in 操作符一样,for in 循环同样在查找对象属性时遍历原型链上的所有属性。

// 修改 Object.prototype
Object.prototype.bar = 1;var foo = {moo: 2};
for(var i in foo) {console.log(i); // 输出两个属性:bar 和 moo
}

hasownprotype:

// foo 变量是上例中的
for(var i in foo) {if (foo.hasOwnProperty(i)) {console.log(i);}
}

函数的声明和表达式:

函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。 一个常见的用法是把匿名函数作为回调函数传递到异步函数中。

var s = function () {}

上述表达的意思是,将一个匿名函数赋值给变量s

foo; // 'undefined'
foo(); // 出错:TypeError
var foo = function() {};

由于 var 定义了一个声明语句,对变量 foo 的解析是在代码运行之前,因此foo 变量在代码运行时已经被定义过了。

但是由于赋值语句只在运行时执行,因此在相应代码执行之前, foo 的值缺省为 undefined。

还有一种特别写法,将命名函数赋值给一个变量:

demo:

var foo = function bar() {bar(); // 正常运行
}
bar(); // 出错:ReferenceError

This的工作原理:

Javascript有一套完全不同于其他语言的this处理机制,五种不同情况下,this的指向个不相同.

1、全局对象:全部范围内使用this,会指向全局对象

2、函数调用:this也会指向全局对象

3、方法调用:this会指向被调用方

demo:

test.foo(); //this指向test

4、调用构造函数:

new f();
如果函数倾向于和 new 关键词一块使用,则我们称这个函数是 构造函数。 在函数内部,this 指向新创建的对象。

5、显示的设置this:

function foo(a, b, c) {}var bar = {};
foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示
foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3

当使用 Function.prototype 上的 call 或者 apply 方法时,函数内的 this将会被 显式设置为函数调用的第一个参数。

因此函数调用的规则在上例中已经不适用了,在foo 函数内 this 被设置成了bar。

闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域总是能够访问外部作用域中的变量。 因为 函数 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。

function Counter(start) {var count = start;return {increment: function() {count++;},get: function() {return count;}}
}var foo = Counter(4);
foo.increment();
foo.get(); // 5

循环中的闭包

一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号

上面的代码不会输出数字 0 到 9,而是会输出数字 10 十次。

当 console.log 被调用的时候,匿名函数保持对外部变量 i 的引用,此时for循环已经结束, i 的值被修改成了 10.

为了得到想要的结果,需要在每次循环中创建变量 i 的拷贝。

为了正确的获得循环序号,最好使用 匿名包裹器(译者注:其实就是我们通常说的自执行匿名函数)。

for(var i = 0; i < 10; i++) {(function(e) {setTimeout(function() {console.log(e);  }, 1000);})(i);
}

JavaScript 中的构造函数和其它语言中的构造函数是不同的。 通过 new 关键字方式调用的函数都被认为是构造函数。

在构造函数内部 - 也就是被调用的函数内 - this 指向新创建的对象 Object。 这个新创建的对象的 prototype 被指向到构造函数的 prototype。

命名空间

只有一个全局作用域导致的常见错误是命名冲突。在 JavaScript中,这可以通过 匿名包装器 轻松解决

(function() {// 函数创建一个命名空间window.foo = function() {// 对外公开的函数,创建了闭包};})(); // 立即执行此匿名函数

匿名函数被认为是 表达式;因此为了可调用性,它们首先会被执行。

( // 小括号内的函数首先被执行
function() {}
) // 并且返回函数对象
() // 调用上面的执行结果,也就是函数对象

结论

推荐使用匿名包装器(译者注:也就是自执行的匿名函数)来创建命名空间。这样不仅可以防止命名冲突, 而且有利于程序的模块化。

另外,使用全局变量被认为是不好的习惯。这样的代码倾向于产生错误和带来高的维护成本。

虽然在 JavaScript 中数组是对象,但是没有好的理由去使用 for in 循环 遍历数组。 相反,有一些好的理由不去使用 for in 遍历数组。

注意: JavaScript 中数组不是关联数组。 JavaScript 中只有对象 来管理键值的对应关系。但是关联数组是保持顺序的,而对象不是。

由于 for in 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 hasOwnProperty 函数, 因此会比普通的 for 循环慢上好多倍。

遍历

为了达到遍历数组的最佳性能,推荐使用经典的 for 循环。

数组的length属性

length 属性的 getter 方式会简单的返回数组的长度,而 setter 方式会截断数组。

var arr = [1, 2, 3, 4, 5, 6];
arr.length = 3;
console.log(arr);arr.length = 6;
console.log(arr);
[1, 2, 3, unique: function, each: function]
[1, 2, 3, unique: function, each: function]
arr
[1, 2, 3, undefined × 3]

由于 Array 的构造函数在如何处理参数时有点模棱两可,因此总是推荐使用数组的字面语法 - [] - 来创建数组。

[1, 2, 3]; // 结果: [1, 2, 3]
new Array(1, 2, 3); // 结果: [1, 2, 3][3]; // 结果: [3]
new Array(3); // 结果: []
new Array('3') // 结果: ['3']// 译者注:因此下面的代码将会使人很迷惑
new Array(3, 4, 5); // 结果: [3, 4, 5]
new Array(3) // 结果: [],此数组长度为 3

JS是弱语言,因此,在进行==比较的时候

会比较两边的操作符而自动进行类型转换

setTimeout只会调用一次。setInterval则每隔X秒会调用一次。

clearTimeout可以清空定时器

settimeout设置时候,建议传入匿名函数

绝对不要使用字符串作为 setTimeout 或者 setInterval 的第一个参数, 这么写的代码明显质量很差。当需要向回调函数传递参数时,可以创建一个匿名函数,在函数内执行真实的回调函数。

另外,应该避免使用 setInterval,因为它的定时执行不会被 JavaScript 阻塞。

JavaScript 的秘密花园相关推荐

  1. JavaScript 秘密花园 http://bonsaiden.github.com/JavaScript-Garden/zh/

    简介 JavaScript 秘密花园是一个不断更新,主要关心 JavaScript 一些古怪用法的文档. 对于如何避免常见的错误,难以发现的问题,以及性能问题和不好的实践给出建议, 初学者可以籍此深入 ...

  2. JavaScript 基础之: JavaScript 秘密花园

    简介 关于作者 这篇文章的作者是两位 Stack Overflow 用户, 伊沃·韦特泽尔 Ivo Wetzel(写作) 和 张易江 Zhang Yi Jiang(设计). 贡献者 贡献者 中文翻译 ...

  3. 《JavaScript 秘密花园》—一些奇奇怪怪的知识

    对象 toString:所有对象都有toString()方法,基本类型除null和undefined外也有 2.toString() 语法错误因为会把 . 当成数字运算,解决办法 2..toStrin ...

  4. JavaScript 基础之 JavaScript 秘密花园

    简介 关于作者 这篇文章的作者是两位 Stack Overflow 用户, 伊沃·韦特泽尔 Ivo Wetzel(写作) 和 张易江 Zhang Yi Jiang(设计). 贡献者 贡献者 中文翻译 ...

  5. [翻译]JavaScript秘密花园 - Type Casting,undefined,eval,setTimeout,Auto Semicolon Insertion - 全部完成PDF打包下载

    JavaScript Garden - 原文 JavaScript Garden - 中文翻译 PDF打包下载 类型转换 JavaScript 是弱类型语言,所以会在任何可能的情况下应用强制类型转换. ...

  6. javascript秘密花园读书笔记

    toString()方法:当数字字面量使用这个方法时会出现错误,这是因为 JavaScript 解析器的一个错误, 它试图将点操作符解析为浮点数字面值的一部分.      例:2.toString() ...

  7. JavaScript 秘密花园[转]

    http://bonsaiden.github.com/JavaScript-Garden/zh/ 转载于:https://www.cnblogs.com/ylemzhang/archive/2011 ...

  8. javascript 秘密花园

    http://bonsaiden.github.io/JavaScript-Garden/zh/  不错推荐学习

  9. javascript秘密花园

    大家请参考 http://www.jb51.net/onlineread/JavaScript-Garden-CN/,真的很好

最新文章

  1. OSError: [WinError 126] 找不到指定的模块/Could not find 'cudart64_90.dll'.
  2. 文巾解题 116. 填充每个节点的下一个右侧节点指针
  3. python最好的教程_喜大普奔~可能是最好的Python教程
  4. 云服务器上MySQL安装教程(Windows)
  5. On the Difference Between Orthogonal Matching Pursuit and Orthogonal Least Squares
  6. CH0805 防线 (二分值域,前缀和,特殊性质)
  7. twisted mysql_Twisted MySQL adbapi返回字典
  8. (50)FPGA数组描述(reg型)
  9. Illustrator 教程,如何在 Illustrator 中创建和编辑图层?
  10. iOS的UILabel设置居上对齐,居中对齐,居下对齐
  11. 整理农行面试软开最常问到的题---------框架
  12. Prefix Sum —— 树状数组+懵逼的组合恒等式
  13. pwm调速流程图小车_51单片机智能小车《pwm调速按键控制小车动作》
  14. 工程管理系统源码-专注项目数字化管理-工程管理
  15. 网络安全绝地求生-面试题
  16. CSS颜色代码大全及a标签超链接颜色改变
  17. android studio多媒体播放器,Android支持全屏、小窗口的视频播放器
  18. OSPF高级配置实现全网互通
  19. Kafka学习笔记 : 消费进度监控 [ 消费者 Lag 或 Consumer Lag ]
  20. 天威TM1668芯片官方资料,讲解,代码,自己写的例程

热门文章

  1. C++ signal信号(SIGHUP、SIGINT、SIGQUIT、SIGILL、SIGTRAP、SIGABRT等等的说明)
  2. 引爆最多的炸弹-c语言dfs递归做法
  3. 人工蜂群算法-要点总结
  4. Centos卸载软件方法
  5. Emacs的日常生活(1)
  6. 【体脂秤方案开发】体脂秤与体重秤的关系
  7. Python日期获取:今天及昨天的年月日等信息
  8. Extension 扩展
  9. 数据可视化_用Matplotlib绘制折线图
  10. com.microsoft.sqlserver.jdbc.SQLServerException: 驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立 安全连接