zoukankan      html  css  js  c++  java
  • javascript高级程序设计 学习笔记 第五章 下

    5.5.5 函数属性和方法

    ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length 和prototype。其中,length属性表示函数希望接收的命名参数的个数。

    function sayName(name){
        alert(name);
    }
    function sum(num1, num2){
        return num1 + num2;
    }
    function sayHi(){
        alert("hi");
    }
    console.log(sayName.length);      //1
    console.log(sum.length);          //2
    console.log(sayHi.length);        //0

    对于 ECMAScript中的引用类型而言,prototype是保存它们所有实例方法的真正所在。换句话说,诸如toString()和valueOf()等方法实际上都保存在prototype名下,只不过是通过各自对象的实例访问罢了。在创建自定义引用类型以及实现继承时,prototype属性的作用是极为重要的。在ECMAScript5中,prototype属性是不可枚举的,因此使用 for-in 无法发现。 每个函数都包含两个非继承而来的方法:apply()和call()。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。首先,apply()方法接收两个参数:一个是在其中运行函数的作用域,另一个是参数数组。其中,第二个参数可以是Array的实例,也可以是arguments对象。例如:

    function sum(num1, num2){
        return num1 + num2;
    }
    function callSum1(num1, num2){
        return sum.apply(this, arguments);
    }
    function callSum2(num1, num2){
        return sum.apply(this, [num1, num2]);
    }
    console.log(callSum1(10,10));   //20
    console.log(callSum2(10,10));   //20
    分析:
    1. 在上面这个例子中,callSum1()在执行 sum()函数时传入了 this 作为 this值(因为是在全局作用域中调用的,所以传入的就是window对象)和arguments对象。
    2. 而callSum2同样也调用了sum()函数,但它传入的则是this和一个参数数组。这两个函数都会正常执行并返回正确的结果。
    在严格模式下,未指定环境对象而调用函数,则this值不会转型为window。除非明确把函数添加到某个对象或者调用 apply()或call(),否则this值将是undefined。

    call()方法与 apply()方法的作用相同,它们的区别仅在于接收参数的方式不同。对于 call() 方法而言,第一个参数是 this 值没有变化,变化的是其余参数都直接传递给函数。换句话说,在使用 call()方法时,传递给函数的参数必须逐个列举出来,如下面的例子所示。

    function sum(num1, num2){
        return num1 + num2;
    }
    function callSum(num1, num2){
        return sum.call(this, num1, num2);
    }
    console.log(callSum(10,10));   //20

    在使用 call()方法的情况下,callSum()必须明确地传入每一个参数。 如果你打算直接传入 arguments 对象,或者包含函数中先接收到的也是一个数组,那么使用 apply() 肯定更方便;否则,选择 call()可能更合适。(在不给函数传递参数的情况下,使用哪个方法都无所谓。)

    事实上,传递参数并非 apply()和 call()真正的用武之地;它们真正强大的地方是能够扩充函数 赖以运行的作用域。下面来看一个例子。

    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        console.log(this.color);
    }
    sayColor();//red
    sayColor.call(this);//red
    sayColor.call(window);//red
    sayColor.call(o);//blue
    分析:
    1. sayColor()也是作为全局 函数定义的,而且当在全局作用域中调用它时,它确实会显示"red"。
    2. 而 sayColor.call(this)和 sayColor.call(window),则是两 种显式地在全局作用域中调用函数的方式,结果当然都会显示"red"。
    3. 当运行 sayColor.call(o) 时,函数的执行环境就不一样了,因为此时函数体内的 this 对象指向了 o,于是结果显示的是"blue"。

    使用 call()(或 apply())来扩充作用域的最大好处,就是对象不需要与方法有任何耦合关系。

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

    window.color = "red";
    var o = { color: "blue" };
    function sayColor(){
        console.log(this.color);
    }
    var objectSayColor = sayColor.bind(o);
    objectSayColor();    //blue
    分析:

    object- SayColor()函数的 this 值等于 o,因此即使是在全局作用域中调用这个函数,也会看到"blue"。

    支持 bind()方法的浏览器有 IE9+、Firefox 4+、Safari 5.1+、Opera 12+和 Chrome。

    每个函数继承的 toLocaleString()和 toString()方法始终都返回函数的代码。返回代码的格 式则因浏览器而异。另外一个继承的valueOf()方法同样也只返回函数代码。

    5.6 基本包装类型

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

    实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们 能够调用一些方法来操作这些数据。

    var s1 = "some text";
    var s2 = s1.substring(2);
    console.log(s1); //some text
    console.log(s2); //me text
    分析:
    1. 变量 s1 包含一个字符串,字符串当然是基本类型值。而下一行调用了s1的substring()方法,并将返回的结果保存在了 s2 中。

    2. 基本类型值不是对象,因而从逻辑上讲它们不应该有方法。

    3. 后台已经自动完成了一系列的处理。

      (1) 创建 String 类型的一个实例;

      (2) 在实例上调用指定的方法;

      (3) 销毁这个实例。

    上面这三个步骤也分别适用于 Boolean 和 Number 类型对应的布尔值和数字值。

    引用类型与基本包装类型的主要区别就是对象的生存期。使用 new 操作符创建的引用类型的实例, 在执行流离开当前作用域之前都一直保存在内存中。而自动创建的基本包装类型的对象,则只存在于一 行代码的执行瞬间,然后立即被销毁。这意味着我们不能在运行时为基本类型值添加属性和方法。 eg:

    var s1 = "some text";
        s1.color = "red";
        console.log(s1.color);   //undefined
    分析:
    1. 第二行创建的 String 对象在执行第三行代码时已经被销毁了。
    2. 第三行代码又创建自己的 String 对象,而该对象没有 color 属性。

    可以显式地调用 Boolean、Number 和 String 来创建基本包装类型的对象。对基本包装类型的实例调用 typeof 会返回"object",而且所有基本包装类型的对象都会被转换 为布尔值 true。

    Object 构造函数也会像工厂方法一样,根据传入值的类型返回相应基本包装类型的实例。例如:

    var obj = new Object("some text");
    console.log(obj instanceof String);   //true
    
    var obj2 = new Object(23);
    console.log(obj2 instanceof Number);   //true
    
    var obj3 = new Object(false);
    console.log(obj3 instanceof Boolean);   //true

    要注意的是,使用 new 调用基本包装类型的构造函数,与直接调用同名的转型函数是不一样的。 例如:

    var value = "25";
    var number = Number(value);  //转型函数 
    console.log(typeof number);  //number
    
    var obj = new Number(value); //构造函数 
    console.log(typeof obj);     //object

    5.6.1 Boolean类型

    Boolean 类型是与布尔值对应的引用类型。

    创建 Boolean 对象:

    var booleanObject = new Boolean(true);

    Boolean 类型的实例重写了 valueOf()方法,返回基本类型值 true 或 false;重写了 toString() 方法,返回字符串"true"和"false"。

    var falseObject = new Boolean(false);
    var result = falseObject && true;
    console.log(falseObject);
    console.log(result);  //true
    
    var falseValue = false;
    result = falseValue && true;
    console.log(result);  //false
    
    console.log(typeof falseObject); //object 
    console.log(typeof falseValue); //boolean 
    console.log(falseObject instanceof Boolean); //true 
    console.log(falseValue instanceof Boolean); //false
    分析:
    1. 使用 false 值创建了一个 Boolean 对象。
    2. 示例中的这行代码是对 falseObject 而不是对它的值(false)进行求值。
    3. 布尔表达式中的所有对象都会被转 换为 true,因此 falseObject 对象在布尔表达式中代表的是 true。
    建议是不要使 用 Boolean 对象。

    5.6.2 Number类型

    Number 是与数字值对应的引用类型。 创建 Number 对象:

    var numberObject = new Number(10);

    与 Boolean 类型一样,Number 类型也重写了 valueOf()、toLocaleString()和 toString() 方法。重写后的 valueOf()方法返回对象表示的基本类型的数值,另外两个方法则返回字符串形式的数值。

    var num = 10; 
    console.log(num.toString()); //"10" 
    console.log(num.toString(2)); //"1010" 
    console.log(num.toString(8)); //"12" 
    console.log(num.toString(10)); //"10" 
    console.log(num.toString(16)); //"a"

    Number 类型的数值格式化为字符串方法:

    (1)toFixed()方法会按照指定的小数位返回数值的字符串表示,例如:

    var num = 10;
    console.log(num.toFixed(2));     //"10.00"

    如果数值本身包含的小数位比指定的还多,那么接近指定的最大小数位的值 就会舍入,如下面的例子所示。

    var num = 10.005;
    console.log(num.toFixed(2));     //"10.01"

    能够自动舍入的特性,使得 toFixed()方法很适合处理货币值。

    在给 toFixed()传入 0 的情况下,IE8 及之前版本不能正确 舍入范围在{(0.94,0.5],[0.5,0.94)}之间的值。IE9 修复了这个问题。

    toFixed()方法可以表示带有 0 到 20 个小数位的数值。但这只是标准实现的范 围,有些浏览器也可能支持更多位数。

    (2)toExponential(),该方法返回以指数表示法(也称 e 表示法) 表示的数值的字符串形式。

    var num = 10;
    console.log(num.toExponential(1)); //"1.0e+1"

    (3)toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指数 (exponential)格式;具体规则是看哪种格式最合适。这个方法接收一个参数,即表示数值的所有数字的 位数(不包括指数部分)。

    var num = 99;
    console.log(num.toPrecision(1)); //"1e+2" 
    console.log(num.toPrecision(2)); //"99" 
    console.log(num.toPrecision(3)); //"99.0"
    分析:
    1. 因为一位数无法准确地 表示 99,因此 toPrecision()就将它向上舍入为 100,这样就可以使用一位数来表示它了。
    2. 两位数表示 99,当然还是"99"。
    3. 三位数表示 99 时,toPrecision()方法返回了"99.0"。
    4. 实际上,toPrecision()会根据要处理的数值决定到底是调用 toFixed()还是调用 toExponential()。 而这三个方法都可以通过向上或向下舍入,做到以最准确的形式来表示带有正确小数位的值。

    与 Boolean 对象类似,Number 对象也以后台方式为数值提供了重要的功能。不建议直接实例化 Number 类型。

    var numberObject = new Number(10);
    var numberValue = 10;
    console.log(typeof numberObject);   //object
    console.log(typeof numberValue);    //number
    console.log(numberObject instanceof Number);  //true
    console.log(numberValue instanceof Number);   //false

    5.6.3 String类型

    String 类型是字符串的对象包装类型。 使用 String 构造函数来创建:

    var stringObject = new String("hello world");

    String 对象的方法也可以在所有基本的字符串值中访问到。其中,继承的 valueOf()、toLocale- String()和 toString()方法,都返回对象所表示的基本字符串值。

    String 类型的每个实例都有一个 length 属性,表示字符串中包含多个字符。来看下面的例子。

    var stringValue = "你好 world";
    console.log(stringValue.length);     //8

    应该注意的是,即使字符串中包 含双字节字符(不是占一个字节的 ASCII 字符),每个字符也仍然算一个字符。

    String 类型方法

    1. 字符方法

    两个用于访问字符串中特定字符的方法是:charAt()和 charCodeAt()。这两个方法都接收一个 参数,即基于 0 的字符位置。

    (1)charAt()方法以单字符字符串的形式返回给定位置的那个字符(ECMAScript 中没有字符类型)。例如:

    var stringValue = "hello world";
    console.log(stringValue.charAt(1));   //e

    (2)如果你想得到 的不是字符而是字符编码,那么就要像下面这样使用 charCodeAt()了。

    var stringValue = "hello world";
    console.log(stringValue.charCodeAt(1));   //101

    (3)ECMAScript 5 还定义了另一个访问个别字符的方法。在支持此方法的浏览器中,可以使用方括号加数 字索引来访问字符串中的特定字符,如下面的例子所示。

    var stringValue = "hello world";
    console.log(stringValue[1]);   //e

    使用方括号表示法访问个别字符的语法得到了 IE8 及 Firefox、Safari、Chrome 和 Opera 所有版本的 支持。如果是在 IE7 及更早版本中使用这种语法,会返回 undefined 值(尽管根本不是特殊的 6 undefined 值)。

    2. 字符串操作方法

    (1) concat(),用于将一或多个字符串拼接起来, 返回拼接得到的新字符串。

    var stringValue = "hello ";
    var result = stringValue.concat("world", "!");
    console.log(result); //"hello world!" 
    console.log(stringValue); //"hello"

    concat()方法可以接受任意多个参数,也就是说可以通过它 9 拼接任意多个字符串。实践中使用更多的还是加号操作符(+)。而且,使用加号操作符在大多数情况下都比使用 concat() 方法要简便易行(特别是在拼接多个字符串的情况下)。

    (2)slice()、substr()和 substring()。

    ECMAScript 还提供了三个基于子字符串创建新字符串的方法:slice()、substr()和 substring()。这三个方法都会返回被操作字符串的一个子字符串,而且也都接受一或两个参数。第一个参数指定子字 符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束(不包含结束位置)。具体来说,slice()和 substring()的第二个参数指定的是子字符串最后一个字符后面的位置。而 substr()的第二个参数指定的则是返回的字符个数。如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置。与 concat()方法一样,slice()、substr()和 substring()也不会修改字符串本身的值——它们只是 返回一个基本类型的字符串值,对原始字符串没有任何影响。

    var stringValue = "hello world";
    console.log(stringValue.slice(3));       //"lo world"
    console.log(stringValue.substring(3));   //"lo world"
    console.log(stringValue.substr(3));      //"lo world"
    console.log(stringValue.slice(3, 7));    //"lo w"
    console.log(stringValue.substring(3,7)); //"lo w"
    console.log(stringValue.substr(3, 7));   //"lo worl"

    传递给这些方法的参数是负值的情况下,它们的行为就不尽相同了。其中,slice()方法会将传 入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个 参数转换为 0。最后,substring()方法会把所有负值参数都转换为 0。

    var stringValue = "hello world";
    console.log(stringValue.slice(-3));       //"rld"
    console.log(stringValue.substring(-3));   //"hello world"
    console.log(stringValue.substr(-3));      //"rld"
    console.log(stringValue.slice(3, -4));    //"lo w"
    console.log(stringValue.substring(3, -4));//"hel"
    console.log(stringValue.substr(3, -4));   //""(空字符串)
    IE 的 JavaScript 实现在处理向 substr()方法传递负值的情况时存在问题,它会 返回原始的字符串。IE9 修复了这个问题。
  • 相关阅读:
    vue使用elementui合并table
    使用layui框架导出table表为excel
    vue使用elementui框架,导出table表格为excel格式
    前台传数据给后台的几种方式
    uni.app图片同比例缩放
    我的博客
    【C语言】取16进制的每一位
    SharePoint Solution 是如何部署的呢 ???
    无效的数据被用来用作更新列表项 Invalid data has been used to update the list item. The field you are trying to update may be read only.
    SharePoint 判断用户在文件夹上是否有权限的方法
  • 原文地址:https://www.cnblogs.com/xmyun/p/6155483.html
Copyright © 2011-2022 走看看