关于原型,js变量的一些理解

首先我要介绍的是基本类型和引用类型的值
 
基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
 
在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。
 
有5种基本数据类型值:Undefined、Null、Boolean、Number和String。这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
 
引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。早操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。
 
 
在此我列举2个Example,虽然很小,但很能说明问题,用心看,和思考
 
1 复制基本类型变量值
 
   在从一个变量向另一个变量复制基本类型值和引用类型值时,也存在不同。如果从一个变量向另一个变量复制基本类型的值,会在变量对象上创建一个新值,然后把该值复制到为新变量分配的位置上。来看一个例子:
var num1=5;
var num2 = num1;
在此,num1中保存的值是5.当使用num1的值来初始化num2时,num2中也保存了值5.但是这里要注意的一点是,num2中的5与num1中的5是完全独立的,该值只是num1中5的一个副本。此后,这两个变量可以参与任何操作而不会相互影响
 
2 复制引用类型变量值
   当从一个变量向另一个变量复制引用类型的值时,同样也会将存储在变量对象中的值复制一份放到为新变量分配的空间中。不同的是,这个值的副本实际上是一个指针,而这个指针指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量,具体列子如下:
 
var obj1 = new Object();
var obj2 = obj1;
obj1.name= "Nicholas";
alert(obj2.name)           // "Nicholas"
 
这之后还要注意的一点就是ECMAScript中所有函数的参数都是按值传递的。
 
到这里就可以引入一些原型的概念了,简而言之,因为对象是引用类型,为此,引用类型的值是按引用类型访问的。
所以当我们想在继承一个对象的基础上还能实现与原有对象的隔离(sperate),我们就需要使用prototype属性!
 
方法如下:
 
function cloneObject(obj)
{
      var clone = function() {};
      clone.prototype = obj;
      return new clone();
}
因为每个构造函数的实例中都会有一个内部属性[prop],它是一个指针,指向对象的原型链(prototype)。
 
天还学习了NAN(Not a Number) ,有一个标准把它定义为不等于自身,判定该方法可以封装为:
 
 function isReallYNaN(x){
   if(x!==x){
       return true;
    }
}
 
今天了解到了javascript中的布尔操作符。非(NOT)、与(AND)、或(OR)
 
1. 
逻辑非(!)可以应用于ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。
逻辑非操作符首先会将它的操作数转换为一个布尔值,然后对其求反。
引申一下,也就是说,逻辑非操作符也可以用于将一个值转换为与其对应的布尔值。同时使用两个逻辑非(!)操作符,即会达到这个目的,实际上就会模拟Boolean()转型函数的行为。其中,第一个逻辑非操作会基于无论什么操作数返回一个布尔值,而第二个逻辑非操作则对该布尔值求反,于是就得到了这个值真正对应的布尔值。
 
2.
加法操作符:除了执行常规的算术运算操作之外,如果有一个操作数是字符串,那么就要应用如下规则:
  • 如果两个操作数都是字符串,那么就将他们拼接起来。
  • 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将它们拼接起来
如果有一个操作数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,然后再应用前面关于字符串的规则。对于undefined和null,则分别调用String()函数并取得字符串“undefined”和“null”.
 
在原始值和对象封装器器中更喜欢原始值(primitive value)
 

 

  • 原始值(primitive value):是存储在栈中的简单数据段,也就是说他们的值直接存在变量访问的位置。
  • 引用值(referrence value):是存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处。

 

 
除了Objects,javascript有5种类型的原始值:booleans,numbers,strings,null,和undefined.
同时,标准库为封装booleans,numbers,strings作为一个对象提供了构造函数。你能创建一个String object通过在其中包含一个字符串的值:
 
var s = new String("hello");
 
在有些方面,字符串对象的行为和字符串原始值表现的作用是相同的。
 
但是不同于primitive Strings,a String object is a true object!
 
typeof "hello";        //"string"
typeof s;                  //“object”
 
这是一个很重要的不同,因为它意味着你不能用内置的操作符去匹配两个独特的String objects的内容。
 
var s1= new String("hello");
var s2= new String("hello");
s1===s2;          //false  它们引用了堆中不同的内存
 
因为每个String object 都是一个单独的对象(object),它只能永久的等于它自身。即时用不严格的等于操作符也是同样的效果。
 
s1==s2;          //false
 
因为这些封装类型的行为并不是完全正确,他们并不会服务于许多目的。他们主要存在的原因是它们有用的方法。javaScript为能进行一些其他的隐式转换制造了这些方便:你能在一个原始值的基础上调用一些方法和抽取一些属性。
比如:“hello”.toUpperCase();             //“HELLO”
 
对于这个隐式封装存在一个奇怪的现象就是你能在原始值的基础上对它设置属性且在本质是没有必然影响的!
 
"hello".someProperty = 17;
"hello".someProperty;          // undefined
 
因为当这个隐式封装每次发生的时候就会产生了一个新的字符串对象,当你在第一个封装对象上设置了一个属性,进行了更新,但是它并没有持续的影响。在原始值的基础上设置属性是没有任何意义的。但是这个行为值得我们所注意。它证明了这是另外一种能隐藏类型错误的实例:如果你在你所期待的一个对象上要设置一个属性值,但是却错误的采用了原始值,你的程序会简单的默认的忽略这个更新然后继续执行其以后的代码。这样就会轻易的导致一些未被发现的错误,让诊断变的艰难。
 
在此有两点需要谨记:
    • 1. Object wrappers for primitive types do not have the same behavior as their primitive values when compared for equality. 
    • 2. Getting and setting properties on primitives implicitly creates object wrappers
    •  

       

 
posted @ 2014-04-02 12:03  gyfvane  阅读(638)  评论(0编辑  收藏  举报