javascript大杂烩

花了点时间学习了下js基础,跟大家分享一下,有不到之处,欢迎指出 :)

关于对象

对象的创建

var newObj = new Object();
// var newObj = {};
newObj['someValue'] = 'val';

一切皆对象

[1,2] instanceof Object // true
{1:2, 3:4} instanceof Object //true

但也有些特殊的对象,如3, ‘str’, true等等,但如果用instanceof测试的话,会发现

'foo' instanceof Object // false
3 instanceof Object // false
true instanceof Object // false

但它们真的也是对象

'foo'.constructor == String // true
true.constructor == Boolean // true
3.constructor == Number // true

还有一个理由

Number.prototype.times = function(func) {
   for(var index = 1; index <= this; index++) {
      func(index);
   }
};
(5).times(print);
// 5 .times(print); //also works
// 加上括号是为了避免出现解析错误(js引擎会以为是小数点)

就连函数也是一个对象

var fn = function(){}
fn.foo = 'hello world'
fn.bar = function()
{
	alert(this.foo);
}

对象的初始化

function User(first, last){
    this.name = first + " " + last;
}
var user = new User("John", "Resig");
// var user = User('John', 'Resig');

一个function,可以看成是一个Class,也可以看成是一个正常的函数,这就麻烦了,因为无论加不加上new这个关键字,function都能正常运行,虽然结果会不一样。

如果看成Class,使用new关键字初始化,那么function里的this指向当前的function。如果不使用new关键字,则function里的this默认指向Window

有两种解决方法,一个是将Class function的首字母大写,如User,这样就能清楚地知道哪些function是Class。但这样还是避免不了写程序时粗心,忘了加new关键字。

另一种方法就是不是用new关键字,在function里自动判断,保证返回的一定是当前对象

function User(first, last){
  if ( this instanceof User ) {
    this.name = first + " " + last;
  } else
    return new User(first, last);
}

更通用的方法是创建一个makeClass方法

// makeClass - By John Resig (MIT Licensed)
function makeClass(){
  return function(args){
    if ( this instanceof arguments.callee ) {
      if ( typeof this.init == "function" )
        this.init.apply( this, args.callee ? args : arguments );
    } else
      return new arguments.callee( arguments );
  };
}

因为函数名未知,所以使用了arguments.callee来实现。

makeClass的使用

var User = makeClass();
User.prototype.init = function(first, last){
  this.name = first + " " + last;
};
var user = User("John", "Resig");
user.name
// => "John Resig" 

对象的继承

每个function都有一个特殊的变量”prototype”,当实例化对象时,这个变量上的各个属性也会被附加到对象上

function Car(model, year, miles)
{
	this.model = model;
	this.year = year;
	this.miles = miles;
}

Car.prototype = {
	info: function() {
		return this.model + this.year + this.miles
	}
}

var car = new Car('Benz', 3, 1500);
alert(car.info());

如果不使用new关键字,prototype就失效了

prototype属性也有一个特殊的属性”constructor”,通过它我们就能实现继承了

Object.prototype.inObj = 1;
 
function A()
{
	this.inA = 2;
}
 
A.prototype.inAProto = 3;
 
B.prototype = new A;            // Hook up A into B's prototype chain
B.prototype.constructor = B;
function B()
{
	this.inB = 4;
}
 
B.prototype.inBProto = 5;
 
x = new B;

闭包与模块化

闭包是一种现象,通常是因为一个function返回了一个内部的function,如

function f1() {
	n = 2011;
	return function f2() {
		alert(n); // 2011
	}
}

可以看到内部function f2成功地得到了f1的local变量,又因为n被f2使用,所以变量n就常驻内存了 从这个角度上说,如果把f1看成一个class,n就变成了私有变量,而f2成为了公共方法,所以就有了模块化的概念

var myNamespace = (function(){
  var myPrivateVar = 0;
  var myPrivateMethod = function(someText){
      console.log(someText);
  }

  return {
      myPublicVar: "foo",
      myPublicFunction: function(bar){
          myPrivateVar++;
          myPrivateMethod(bar);
      }
  }
})();

其他

避免命名污染的方法

// self executing
// if you want some var global accessable, put "window." ahead
(function() {
  var myVar = 2;
  alert(myVar);
  window.globalVar = 3;
})();

强大的prototype

Array.prototype.contains = function(value) {  
    for (var i = 0; i < this.length; i++) {  
        if (this[i] == value) return true;  
    }  
    return false;  
}

var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");

方便的”+”

// Quick hex to dec conversion:
+"0xFF";              // -> 255

// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();

// Safer parsing than parseFloat()/parseInt()
parseInt("1,000");    // -> 1, not 1000
+"1,000";             // -> NaN, much better for testing user input
parseInt("010");      // -> 8, because of the octal literal prefix
+"010";               // -> 10, `Number()` doesn't parse octal literals 

// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null;                // -> 0;

// Boolean to integer
+true;                // -> 1;
+false;               // -> 0;

// Other useful tidbits:
+"1e10";              // -> 10000000000
+"1e-4";              // -> 0.0001
+"-12";               // -> -12

注意:如果是字符串与数字相加的话,结果还是字符串,如”hello” + 3,结果为”hello3”

通过[]来获取/设置Object的属性

a = {}
a['class'] = 'hello'; // access reversed property
a['have space'] = 'world'; // has space
a['.class .subclass'] = 'value'; // can have .

String的split和replace可以包含正则

"hello world   with  spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]

var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"

函数定义式与函数表达式

alert(typeof eve); //结果:function
alert(typeof walle); //结果:undefined
function eve() { //函数定义式
  alert('I am Laruence');
};
var walle = function() { //函数表达式
}
alert(typeof walle); //结果:function

对于函数定义式,会将函数定义提前,而对于函数表达式,只有在执行过程中才会计算

作用域

对于下面的demo

var name = 'laruence';
function echo() {
     alert(name);
     var name = 'eve';
     alert(name);
     alert(age);
}
echo();

输出结果为

undefined
eve
[ReferenceError]

原因是js在执行函数之前,会有一个预编译的过程,这个过程中会把局部变量提取出来,放到scope chain中,value都为undefined(不包括传递过来的参数),所以在执行echo函数时,name的值在设置为”eve”前,为undefined

参考: * simple class instantiation/ * hidden features of javascript * Object Oriented Programming in JavaScript * module pattern * javascript的作用域原理


--EOF--

若无特别说明,本站文章均为原创,转载请保留链接,谢谢