JavaScript-变量和引用类型

变量、作用域和内存问题

  1. 对于引用数据类型的值,我们可以为它添加属性和方法,也可以改变和删除属性和方法。
  2. 将一个基本类型变量赋值给另一个值时,两个值是完全独立的,不会相互影响。但一个变量向另一个变量复制引用类型的值时两个变量将引用一个变量。
var o1=new Object();
var o2=o1;
o1.name="Nicholas";
alert(o2.name);//"Nichplas"
  1. **所有的函数都是按值传递的。**如以下例子:
function addTen(num){
    num+=10;
    return num;
}
var count=20;
var result=addTen(count);
alert(count);//20
alert(result);//30
  1. 检测类型

在检测基本数据类型时可以用typeof,但在检测引用类型的值时,我们可以用instanceof。

alert(person instanceof Object);
alert(colors instanceof Array);
alert(pattern instanceof RegExp);
  1. 执行环境与作用域

执行环境(execution context)定义了变量或函数有权访问的其他数据,决定了它们各自的 行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中,我们编写的代码无法访问这个对象,但解释器在处理数据时会在后台使用它。

全局执行环境时最外围的执行环境。

每个函数都有自己的执行环境。

当代码在一个环境中执行时,会创建变量对象的一个作用域链(scope chain)。作用域链的用途是保证对执行环境有权访问的 所有变量和函数的有序访问。

引用类型

1. Object类型

有两种创建Object类型的方式:一种是用new Object():

var person =new Object();
person.name="Nicholas";
person.age=25;

另一种是采用对象字面量表示法。对象字面量是对象定义的一种简写形式,可以简化创建包含大量属性的对象的过程,如下:

var person={
    name:"Nicholas",
    age=25
}

另外,如果留空其花括号效果与new Object()一样

var person={}//new Object()
person.name="Nicholas";
person.age=25;

一般访问对象属性时都是点表示法,JavaScript中也可以使用方括号表示法来访问对象的属性。

alert(person["name"]);
alert(person.name);

如果属性名中包含会导致语法错误的字符,或者属性名使用关键之或保留字时就只能使用方括号表示法:

person["first name"]="Nicholas";

2. Array类型

  1. ECMAScript数组的每一项都可以保存任何类型的数据。数组的大小也是可以动态调整的。创建数组的方式有两种:一种是使用Array构造函数:
var color1=new Array();
var color2=new Array(20);//数组大小为20
var color3=new Array("red","blue","green");
var color4=new Array("Grag")

给构造器传递一个值时,如果是数值就创建给定项的数组,如果是其他类型,就会创建包含那个值的只有一项的数组。new 是可以省略的。

另一种方法是使用数组字面表示法。

var colors=["red","blue","green"];
var name=[];
var value=[1,2,];//最好不要这样
var options=[,,,,,];//最好不要这样
  1. 读取数组的值时,要使用方括号+数字索引
alert(colors[0]);
colors[2]="black";//修改第三项
colors[3]="brown";//新增第四项
  1. 通过数组的length属性可以读取数组的大小,而且length属性是可以设置的,通过设置length可以移除或新增项:
var color=["red","blue","green"];
color.length=2;
alert(color[2]);/undefined

利用length属性可以方便地在数组末尾添加新项

var colors=["red","blue","green"];
colors[colors.length]="black";
colors[colors.length]="brown";
  1. 对于一个网页或者一个全局作用域来书可以使用instanceof来检测数组:
if(value instanceof Array){   
}

利用Array.isArray()方法可以不管是在哪个执行环境中创建的。

if(Array.isArray(value)){
}
  1. 通过toString()方法返回数组中每个值的字符串形式拼接而成的以逗号为分隔符的字符串:
var color=["red","blue","green"];
alert(color.toString);//red,blue,green
alert(color.valueof());//red,blue.green
alert(color);

另外还可以用toLoaleString()方法。

可以用join()方法指定分隔符:

var color=["red","blue","green"];
alert(color.join("||"));//red||bblue||green
  1. 栈方法

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构。push()方法可以接受任意数量的参数把他们逐个添加到数组的末尾,并返回修改后数组的长度。pop()方法是从数组的末尾移除一项,减少length的值,并返回移除的项。

var colors=new Array;
var count=colors.push("red","green");
alert(count);
count=colors.push("black");
alert(count);
var item=colors.pop();
alert(item);
alert(colors.length);
  1. 队列方法

队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)。相关的方法是shift()方法,移除数组中的第一项并返回该值,数组的length减一。

  1. 重排序方法

reverse()和sort()

var values=[1,2,3,4];
values.reverse();
alert(values);//4,3,2,1
var value=[0,1,5,10,15];
value.sort();
alert(value);//0,1,10,15,5

注意,sort()方法是先调用每一项的toString方法得到字符串后再排序的。

为了得到我们想要的排序,sort()方法可以接受一个比较函数作为参数。比较函数接受两个参数,如果第一个参数应该位于第二个参数前则返回一个负数,相等返回0,第一个参数在后面则返回一个正数,如下:

function compare(value1,value2){
    if(value1<value2){
        reture -1;
        else if(value1>value2){
            reture 1;
        }else{
            return 0;
            }
    }
}
var value=[0,1,5,10,15];
value.sort(compare);
alert(value);//0,1,5,10,15

可以有更简单的比较函数:

function compare(value1,value2){
    return value2-value1;
}
  1. 操作方法
  • concat():创建当前数组的一个副本然后将接受到的参数添加到这个副本的末尾
  • slice():基于当前数组中的一个或多个项创建一个新数组。接受一个参数时返回该参数指定位置开始到数组末尾的全部项。两个参数的话放回起始到结束位置的所有项(不包括结束位置)
  • splice():向数组的中部插入项。有以下三种方式:
    • 删除:指定两个参数:起始位置和项数,如:splice(0,2)删除前两项
    • 插入:提供三个参数:起始位置、0(删除0项)、要插入的项,如:splice(2,0,“red”,“green”)
    • 替换:如:splice(2,1,“red”,“green”)
    var colors=["red","blue","green"];
    var color1=colors.concat("black","yellow",["gray","blown"]);
    alert(color1);
    var color2=colors.slice(2,5);
    alert(color2);
    alert(colors);
    var color3=colors.splice(1,2,"white");
    alert(color3);
    alert(colors);
  1. 位置方法

有两个位置方法:indexof()和lastIndexOf(),这两个方法都接受两个参数:要查找的项和查找起点的索引。indexof()是从数组的开头找,lastIndexOf是从数组的末尾找。

   var num=[1,2,3,4,2,1,23,42,1,2,3];
   alert(num.indexOf(2,0));//1
  alert(num.lastIndexOf(2,8));//4
  1. 迭代方法
  2. 有5种迭代方法。传入这些方法中的函数会接受三个参数:数组项的值、该项在数组中的位置、数组对象本身。一下是这5中迭代方法:
  • every():如果该函数对每一项都返回true则返回true。

  • filter():返回该函数会返回ture的项组成的数组。

  • forEach():对数组中的每一项运行该函数,无返回值。

  • map():返回该函数调用的结果组成的数组。

  • some:如果该函数对任一项返回true则放回true。

    var num=[1,2,3,4,2,1,23,42,1,2,3];
       var eve=num.every(function(item,index,Array){
           return(item>2);
       });
       alert(eve);
       var filt=num.filter(function(item,index,Array){
           return(item>2);
       });
       alert(filt);
       num.forEach(function (item,index,Array) {
            document.writeln(item);
       });
        var maps=num.map(function(item,index,Array){
            return (item>2);
        });
    
       alert(maps);
       document.writeln("!!");
       var so=num.some(function(item,index,Array){
           return(item>2);
       });
       alert(so);
    
  1. 缩小方法:reduce()和reduceRight(),两个方法都会迭代数组的所有项然后构建一个最终返回的值。reduce()从数组的第一项开始,逐个遍历到最后,reduceRight()是从数组的最后一项开始,向前遍历到第一项。

两个方法都接受两个参数:一个在每一项上调用的初始值和作为缩小基础的初始值(可选)。函数可接受四个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传个下一项。如:

   var sum=[1,2,3,4,5,6];
   var result=sum.reduce(function(pre,cur,index,array){
       return pre+cur;
   });
   alert(result);//21
   var results=sum.reduceRight(function(pre,cur,index,array){
       return pre+cur;
   });
   alert(results);//21

3. Date类型

ECMAScript中的Date类型是在早期Java中的java.util.Date类基础上创建的。创建一个Date类型如下:

var now=new Date();

不传递参数的情况下新创建的对象自动获得当前的日期和时间。要想创建特定的日期对象,必须传入日期的毫秒数(从UTC时间1970年1月1日午夜起至该日期为止经过的毫秒数)。为简化计算过程,有两个方法:Date.parse()和Date.UTC()。Date.parse()接受一个表示参数的字符串,然后返回该日期的毫秒数。日期格式依赖于浏览器的地区设置。若地区为美国浏览器通常接受以下格式:

  • “月/日/年”,如:2/16/2020
  • February 2,2020
  • Tue May 25 2004 00:00:00 GMT-0700
  • ISO 8601 扩展格式 YYYY-MM-DDTHH:mm:ss:ssZ,如:2004-05-25T00:00:00
var da=new Date(Date.parse("2/16/2020"));
alert(da);//Sun Feb 16 2020 00:00:00 GMT+0800 (中国标准时间)

Date.UTC()同样返回毫秒数,但它传入的参数不同,参数分别是年份、基于0的月份(月份从0开始)、月中的第几天、时、分、秒以及毫秒。这些参数中前两个参数是必须的。天数默认为1,其它统统默认为0。

var das=new Date(Date.UTC(2020,1));
alert(das);//Sat Feb 01 2020 08:00:00 GMT+0800 (中国标准时间)

Date类型有很多相关的方法。

4. RegExp类型

ECMAScript通过RegExp类型来支持正则表达式。创建一个正则表达式如下:

var expression=/ pattern/flags;

其中的pattern(模式)部分可以是任何简单或者复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。每个正则表达式都可带有一个或多个flag(标志),用来表明正则表达式的行为。正则表达式的匹配模式支持下列三个标志:

  • g:global模式,即模式将被应用于所有的字符串
  • i:表示不区分大小写(case-insensitive)模式
  • m:表示多行(multiline)模式,即在到达一行文本末尾是还会继续查找下一行中是否存在与模式匹配的项
var p1=/at/g;//匹配字符串中所有at的实例
var p2=/[bc]at/i;//匹配第一个"bat"或"cat"
var p3=/.at/gi;//匹配所有以at结尾的三个字符的组合,不区分大小写
//  ([{\^$|)?*+.]} 这些都需要对他们进行转义
var p4=/.at/gi;//匹配.at,不区分大小写
var p5=new RegExp("[bc]at","i");//与p2相同

需注意的是传递给构造函数的两个参数都是字符串,所以有时要对字符进行双重转义(字符\转义为\\,而在字符串中就会变成\\\\)。

注意使用正则表达式字面量和使用RegExp构造函数创建的正则表达式不一样,字面量始终会共享同一个RegExp实例,而构造函数创建的每一个新的EegExp实例都是一个新实例。但ECMAScript5规定了使用字面量必须像直接调用RegExp构造函数一样,每次创建新的实例。

var re=null,i;
for(i=0;i<10;i++){
    re=/cat/g;
    document.writeln(re.test("catastrophe")) ;
}
for(i=0;i<10;i++){
    re=new RegExp("cat","g");
    document.writeln(re.test("catastrophe")) ;
}
//全部为 true
  1. 实例属性

RegExp每个实例都具有以下属性:

  • global:布尔值,表示是否设置了g标志
  • ignoreCase:布尔值,表示是否设置了i标志
  • lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起
  • multiline:布尔值,表示是否设置了m标志
  • source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回。
var p1=/\[bc\]at/i;
document.writeln(p1.global);//false
document.writeln(p1.ignoreCase);//true
document.writeln(p1.multiline);//false
document.writeln(p1.lastIndex);//o
document.writeln(p1.source);//"\[bc\]at"
  1. RegExp实例方法

RegExp对象的主要方法是exec(),该方法是专门为捕获组而设计的。exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配信息的数组,无匹配项的情况下返回null。返回的数组包含两个额外的属性:index和input。index表示匹配项在字符串中的位置,input表示应用正则表达式的字符串。数组中第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串。

var text="mom and dad and baby";
var p=/mom( and dad( and baby)?)?/gi;
var matches=p.exec(text);
document.writeln(matches.index);//0
document.writeln(matches.input);//mom and dad and baby
document.writeln(matches[0]);//mom and dad and baby
document.writeln(matches[1]);//and dad and baby
document.writeln(matches[2]);//and baby
  1. RegExp构造函数属性
长属性名短属性名说明
input$_最近一次要匹配的字符串
lastMatch$&最近一次的匹配项
lastParen$+最近一次匹配的捕获组
leftContext$`input字符串中lastMatch之前的文本
multiline$*布尔值,表示是否所有表达是都使用多行模式
rightContext$’input字符串中lastMatch之后的文本

5. Function类型

函数实际上是对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。函数名实际上是指向对象的指针,不会与某个函数绑定。函数定义如下:

function sum1(n1,n2){
return n1+n2;
}
var sum2=function(n1,n2){
return n1+n2;
}
//两种方式同样的效果
var sum3=new Function("n1","n2","return n1+n2");//不推荐

因为函数名只是指针,所以一个函数可以有多个函数名

function sum1(n1,n2){
return n1+n2;
}
var add=sum;
alert(sum1(10,10));
alert(add(10,10));
  1. 没有重载。

  2. 解释器在向执行环境加载数据时会率先读取函数声明,而函数表达式必须等到解析器执行到它所在的代码行才会被解释执行。

  3. 函数名可以作为值来使用。不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回。

  4. 函数内部有两个特殊对象:argument和this。

argument前面有介绍的用于保存函数参数,值得一提的时这个对象还有一个callee的属性,指向函数自身。

function fun(num){
    if(num<=1){
        return 1;
    }else{
        return num*arguments.callee(num-1);
    }
}

this类似与java和C#中的this。即this引用的时函数据以执行的环境对象。

window.color="red";
var o={color:"blue"};
function sayColor() {
    alert(this.color);
}
sayColor();//red
o.saycolor=sayColor;
alert(o.saycolor());//blue

另外还有一个函数对象的属性:caller,保存着调用当前函数的函数的引用。

  1. 每个函数都包含两个属性:length和prototype。

length表示函数希望接收的命名参数的个数。

function sayname(name) {
alert(name);
}
function sum(n1,n2) {
    return n1+n2;
}
function sayHi() {
alert("hi")
}
alert(sayname.length);//1
alert(sum.length);//2
alert(sayHi.length);//0

prototype是保存他们所有实例方法的真正所在。toString和valueof等方法实际上都保存在prototype名下。每个函数都包含两个非继承而来的方法:apply()和call()。apply()方法接收两个参数:运行函数的作用域和参数数组。

function sum(n1,n2) {
    return n1+n2;
}
function callsum1(n1,n2) {
return sum.apply(this,arguments);
}
function callsum2(n1,n2) {
return sum.apply(this,[n1,n2]);
    //return sum.call(this,n1,n2)
}
alert(callsum1(10,10));
alert(callsum2(10,10));

call()方法与apply的差别仅仅在于接受参数的方式不同。

apply和call()真正强大的地方在于能扩充函数赖以运行的作用域。

window.color="red";
var o={color:"blue"};
function getcolor() {
alert(this.color);
}
getcolor.call(this);//red
getcolor.call(window);//red
getcolor.call(o);//blue

ECMAScript5还定义了一个方法:bind()。这个方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。

window.color="red";
var o={color:"blue"};
function getcolor() {
alert(this.color);
}
var bindgetcolor=getcolor.bind(o);
bindgetcolor();//blue

6. 基本包装类型

ECMAScript提供了3个特殊的 引用类型:Boolean、Number和String。

  1. Boolean类型是与布尔值对应的引用类型
  2. Number 是数字值对应的引用类型
  3. String类型是字符串的对象包装类型,它提供以下方法:
  • 字符方法:charAt()(返回给定位置的字符)和charCodeAt()(返回给定位置的字符编码)

  • 字符串操作方法:concat()(将字符串拼接起来)、slice()、substr()、substring()

  • 字符串的位置方法:indexof()和lastIndexof()

  • trim方法:创建一个字符串的副本然后删除其前置和后缀的空格并返回。

  • 大小写转换方法:toLowerCase()、toLocaleLowerCase()、toUppercase()和tolocalUpperCase()

  • 模式匹配方法:match()、search()、replace()和split()

  • localeCompare()方法

  • fromCharCode()方法:接受一或多个字符编码,然后将他们转换成一个字符串。与charCodeAt()执行相反的操作。

  • HTML方法(不推荐使用)

    <script>
    function away() {
    document.writeln("-")
    }
    var ch="abcdefghi";
    document.writeln(ch.charAt(2));
    away();
    document.writeln(ch.charCodeAt(2));
    away();
    document.writeln(ch.slice(1,2,"aaa"));
    away();
    document.writeln(ch.substr(2,4));
    away();
    document.writeln(ch.substring(2,4));
    away();
    document.writeln(ch.indexOf("c"));
    away();
    document.writeln(ch.lastIndexOf("c"));
    away();
    document.writeln(ch.trim());
    away();
    document.writeln(ch.toLowerCase());
    away();
    document.writeln(ch.toLocaleLowerCase());
    away();
    document.writeln(ch.toUpperCase());
    away();
    document.writeln(ch.toLocaleUpperCase());
    away();
    document.writeln(ch.match(/hi/));
    away();
    document.writeln(ch.search(/hi/));
    away();
    document.writeln(ch.replace("hi","hijk"));
    away();
    document.writeln(ch.split("d"));
    away();
    document.writeln(ch.localeCompare("cde"));
    //运行结果:c - 99 - b - cdef - cd - 2 - 2 - abcdefghi - abcdefghi - abcdefghi - ABCDEFGHI - ABCDEFGHI - hi - 7 - abcdefghijk - abc,efghi - -1 
    </script>
    

7. 单体内置对象

  1. Global对象,包含以下一些方法:
  • URI编码方法
  • eval()方法 :eval()方法就像是一个完整的ECMAScript解析器
  • Global对象的属性:特殊的值(如 undefined、NaN、Infinity等)以及所有原生引用类型的构造函数
  • window对象
  1. Math对象
  • Math对象的属性

    • Math.E —>自然对数的底数e

    • Math.LN10—>10的自然对数

    • Math.LN2—>2的自然对数

    • Math.LOG2E—>2为底e的对数

    • Math.LOG10E—>10为底e的对数

    • Math.PI—>pi的值

    • Math.SQRT1_2—>1/2的平方根

    • Math.SQRT2—>2平方根

  • min()和max()方法

  • 舍入方法:Math.cell()(向上舍入)、Math.floor()(向下舍入)、Math.round()(标准舍入)

  • random()方法:返回0-1之间的随机数

  • 其他如正余弦、绝对值


参考:《JavaScript高级程序设计》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值