Matthew Note

JavaScript Note

作用域和声明提前


Javascript并不被作用域{}所控制,所以函数内声明的变量在所有的函数内的scope里都是可见的,因此可以把函数所有的变量都放在最开始声明

1
2
3
4
5
6
var scope = "global"
function func(){
console.log(scope)// undefine
var scope = "local"
console.log(scope) // "local"
}
  • 没初始化的变量默认为undefined

NaN Infinity


不能够用x == NaN 判断是否是NaN或者Infinity,可以使用isNaN()或者isInfinity()来判断

属性的四个特性


数据属性

  • value
  • writable
  • enumerable
  • configurable

存取器属性

不具有value和writable特性,写特性是由有没有setter方法决定的

  • get
  • set
  • enumerable
  • configurable
1
2
3
4
5
Object.getOwnPropertyDescriptor({x:1}, 'x')
//return {value:1, writable:true, enumerable:true, configurable:true}
Object.defineProperty(obj, 'x', {value:1, writable:true, enumerable:true, configurable:true})//设置属性
//不能修改继承属性

this


  1. 在构造函数中的this指向所创建的对象
  2. 一般的this指向他的上下文

注意他并不遵循 lexical scope, 只是表示上下文(context)

建议不要使用this

You actually don’t want to access this in particular, but the object it refers to. That’s why an easy solution is to simply create a new variable that also refers to that object. The variable can have any name, but common ones are self and that.

1
2
3
4
5
6
7
function MyConstructor(data, transport) {
this.data = data;
var self = this;
transport.on('data', function() {
alert(self.data);
});
}

使用bind

Explicitly set this of the callback

It might look like you have no control over the value of this, because its value is set automatically, but that is actually not the case.

Every function has the method .bind [docs], which returns a new function with this bound to a value. The function has exactly the same behavior as the one you called .bind on, only that this was set by you. No matter how or when that function is called, this will always refer to the passed value.

1
2
3
4
5
6
7
function MyConstructor(data, transport) {
this.data = data;
var boundFunction = (function() { // parenthesis are not necessary
alert(this.data); // but might improve readability
}).bind(this); // <- here we are calling `.bind()`
transport.on('data', boundFunction);
}

In this case, we are binding the callback’s this to the value of MyConstructor’s this.

Set this of the callback - part 2

Some functions/methods which accept callbacks also accept a value to which the callback’s this should refer to. This is basically the same as binding it yourself, but the function/method does it for you. Array#map [docs] is such a method. Its signature is:

array.map(callback[, thisArg])
The first argument is the callback and the second argument is the value this should refer to. Here is a contrived example:

1
2
3
4
5
6
var arr = [1, 2, 3];
var obj = {multiplier: 42};
var new_arr = arr.map(function(v) {
return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument
1
2
3
4
5
6
7
SmaApi.prototype.trigger_all = function(obj){
var propNames = Object.getOwnPropertyNames(obj);
propNames.forEach(function(name) {
this.trigger(name);
}, this);
}

argument

函数会有一个argument属性对应于他的实参

callee和caller属性

  • callee 正在执行的函数
  • caller 调用它的函数

函数


prototype属性

每个函数都有一个prototype属性,这个属性是一个对象的引用,每个函数都包含不同的原型对象

call方法和apply方法

他可以用来绑定一个函数func到任意对象obj

1
2
func.call(obj, args...)
func.apply(obj, [args...])

bind

它和apply和call的不同是,bind返回的是一个函数

1
var func2 = func.bind(obj, args)

Function() 构造函数

Function()创建的函数并不使用词法作用于,所以他作为嵌套函数的时候不能捕获上层函数的对象

不完全函数

把一个函数调用拆成,若干个子调用f(1,2,3,4,5)=>f(1,2)(3,4)(5)

类包含一个构造函数,一个prototype,对于prototype相同的对象是属于一类的。

Javascript里面的类实际上感觉就是用对象构造对象,他没有其他OO中类的概念

  • 构造函数中的属性是等同于static
  • 而prototype的等同于方法/属性
  • 构造函数并不是生成对象的主体,主体是prototype,构造函数只能作为类似静态方法的方式操作

TIP


  • 使用分号
  • 不区分整数和浮点
  • 如果没使用var声明一个变量,那么他会默认变成全局的。
  • a = a || a.func()
  • JSON.stringify and JSON.parse
  • Javascript 相等运算符比较对象时,比较的是引用而不是值,可以用equals()来做完整比较
  • 代码质量检查 jslint.com
  • let 声明块级作用域的变量
  • const 声明常量 v >1.8