JavaScript Garden

https://bonsaiden.github.io/JavaScript-Garden/zh/#intro

对象

对象:创建,属性,读取,设置

// literal
var a = {}

// set property
a.prop = 'test'  
var a = { prop:'test' }

// read 
a.prop  
a[prop]

// delete property
obj.bar = undefined;  
obj.foo = null;  
delete obj.baz;

// property name
Object properties can be both notated as plain characters and as strings.字符串或者普通字符声明.但要避免关键字的出现  

面向对象编程的基本原理,做法

prototype

原型继承: prototypal inheritance

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

还有就是 实现基于类的继承 classic model

hasOwnProperty

为了判断一个对象是否包含自定义属性而不是原型链上的属性, 我们需要使用继承自 Object.prototype 的 hasOwnProperty 方法。

注意: 通过判断一个属性是否 undefined 是不够的。 因为一个属性可能确实存在,只不过它的值被设置为 undefined。 hasOwnProperty 是 JavaScript 中唯一一个处理属性但是不查找原型链的函数。

函数

函数声明 函数表达式 匿名函数 立即执行函数表达式 ---- 匿名包装器

this

全局范围 函数调用 方法调用 调用构造函数 显示设置this

// 关于 this call apply
function add(a, b){console.dir(this);console.log(a+b)}  
function sub(a, b){console.dir(this);console.log(a*b)}  
add(3,5);  
"Window"

sub(3,5);  
"Window"

add.call(sub, 3, 5);  
"sub(a, b)"

sub.apply(add, [3, 5]);  
"add(a, b)"

闭包和引用

closure & reference

构造函数

使用new

对于:工厂函数:简单的来讲就是不用new ,用return 显式的返回对象

qita

变量提升 hosting

名称解析顺序

JavaScript 中的所有作用域,包括全局作用域,都有一个特别的名称 this 指向当前对象。

函数作用域内也有默认的变量 arguments,其中包含了传递到函数中的参数。

比如,当访问函数内的 foo 变量时,JavaScript 会按照下面顺序查找:

1.当前作用域内是否有 var foo 的定义。  
2.函数形式参数是否有使用 foo 名称的。  
3.函数自身是否叫做 foo。  
4.回溯到上一级作用域,然后从 #1 重新开始。  

命名空间

立即执行函数表达式,解决变量命名冲突

(function() {
    // 函数创建一个命名空间

    window.foo = function() {
        // 对外公开的函数,创建了闭包
    };

})(); // 立即执行此匿名函数

类型

typeof

instanceof

Object.prototype.toString()
Object.prototype.toString.call(obj).slice(8, -1);

Object.prototype.toString()

Class

一列表示对象的内部属性 [[Class]] 的值。

[[Class]] 的值只可能是下面字符串中的一个: Arguments, Array, Boolean, Date, Error, Function, JSON, Math, Number, Object, RegExp, String. 可以获得是基本类型还是引用类型。获得准确的数据类型。

而对于instanceof来讲:

new String('foo') instanceof String; // true      无法准确获得数据类型  
new String('foo') instanceof Object; // true

'foo' instanceof String; // false        不能用于检测基本类型。  
'foo' instanceof Object; // false  

为了获取对象的 [[Class]],我们需要使用定义在 Object.prototype 上的方法 toString。也就是可以获得所有的类型。

Object.prototype.toString.call([])    // "[object Array]"  
Object.prototype.toString.call({})    // "[object Object]"  
Object.prototype.toString.call(2)    // "[object Number]"  
Object.prototype.toString.call(obj).slice(8, -1);  

instanceof 操作符

instanceof 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。

setTimeout setInterval

定时处理不是 ECMAScript 的标准,它们在 DOM (文档对象模型) 被实现。 基于 JavaScript 引擎的计时策略,以及本质上的单线程运行方式,所以其它代码的运行可能会阻塞此线程。 因此没法确保函数会在 setTimeout 指定的时刻被调用。

this

function Foo() {  
    this.value = 42;
    this.method = function() {
        // this 指向全局对象
        console.log(this.value); // 输出:undefined
    };
    setTimeout(this.method, 500);
}
new Foo();  

作为第一个参数的函数将会在全局作用域中执行,因此函数内的 this 将会指向这个全局对象。

处理可能的阻塞调用

最简单也是最容易控制的方案,是在回调函数内部使用 setTimeout 函数。

function foo(){  
    // 阻塞执行 1 秒
    setTimeout(foo, 100);
}
foo();  

这样不仅封装了 setTimeout 回调函数,而且阻止了调用指令的堆积,可以有更多的控制。 foo 函数现在可以控制是否继续执行还是终止执行。