JavaScript 对象基础

1. 什么是 Object 对象?

JavaScript 中的所有事物都是对象,如:字符串、数值、数组、函数等,每个对象带有属性和方法。
对象的属性:反映该对象某些特定的性质的,如:字符串的长度、图像的长宽等;
对象的方法:能够在对象上执行的动作。例如,表单的“提交”(Submit),时间的“获取”(getYear)等;
JavaScript 提供多个内建对象,比如 String、Date、Array 等等,使用对象前先定义。

2. 如何定义对象?
  • 字面量创建法

    var person = {
      name: "Grace",
      age: 18,
      gender: "female"
    };
    
  • 借助 new 操作符 + Object 创建

    var person = new Object();
    person.name = "Grace";
    
    //下面是另一种创建属性的方式
    
    var myHeight = "height";
    var myHeightValue = "163cm";
    person[myHeight] = myHeightValue;
    person.height === person[myHeight]; // true
    
  • 构造函数

    function Person(name, age, gender) {
      this.name = name;
      this.age = age;
      this.gender = gender;
    }
    
    var kitty = new Person("Kitty", 8, "female");
    var grace = new Person("Grace", 18, "female");
    
    kitty.name; // "Kitty"
    grace.age; // 18
    
    Person.prototype.greet = function () {
      return ("Hello, I\'m " + this.name + "!");
    }
    
    grace.greet(); // "Hello, I'm Grace!"
    
    1. 该方法可以利用一个构造函数(new Person(...))来创建很多个对象,并且构造函数中的 this 会在创建的时候,指向新创建的对象,并且默认返回 this,所以在最后就不用 return this 了。

    2. 如果想要给这些对象创建一个新的属性,例如 greet 就只要将这个属性加到他们的原型链上就好了,即 Person.prototype.greet ,这样就可以让他们的 greet 函数都可以共享一个属性,节省内存。

    3. 需要注意的是:

      kitty.greet; // function: Person.greet()
      grace.greet; // function: Person.greet()
      kitty.greet === grace.greet // true
      

      但是如果是下面这样写:(直接写在构造函数里)

      function Person(name) {
        this.name = name;
        this.hello = function () {
          alert('Hello, I\'m ' + this.name + '!');
        }
      }
      
      var kitty = new Person("Kitty");
      var grace = new Person("Grace");
      
      kitty.hello; // function: Person.hello()
      grace.hello; // function: Person.hello()
      kitty.hello === grace.hello; // false
      

      这个时候它们并不是共用一个函数,只不过是函数的名称和内容相同而已,所以实际上是两个不同的函数。

    4. 上面的第一段代码中:

      return ("Hello, I\'m " + this.name + "!");
      

      可以写成:

      return (`Hello, I'm ${this.name}!`);
      

这里主要是参考了廖雪峰前辈主页的创建对象。

3. 如何获取对象的值?

通过(.)或者([])来获取,其实在上面创建的时候就有这样的例子了,我们把它单独拎出来:

kitty.name; // "Kitty"
grace["age"]; // 18

var person = {};
var myHeight = "height";
var myHeightValue = "163cm";
person[myHeight] = myHeightValue;
person[myHeight]; // "163cm"
person.height; // "163cm"
person["height"]; // "163cm"

但是按照规范最好用上面两种,不怎么用 person[myHeight] 这样的。

4. Object 对象属性和方法
  • String 对象
    属性如下:(之后的对象前两个属性类似)

    属性名 作用
    constructor 所建立对象的构造函数
    prototype 能够为对象加入的属性和方法
    length 返回字符串的字符长度

    方法如下:

    方法名 作用
    charAt() 返回指定索引位置的字符
    charCodeAt() 返回指定索引位置字符的 Unicode 值
    concat() 连接两个或多个字符串,返回连接后的字符串
    fromCharCode() 将 Unicode 转换为字符串
    indexOf() 返回字符串中检索指定字符第一次出现的位置
    lastIndexOf() 返回字符串中检索指定字符最后一次出现的位置
    localeCompare() 用本地特定的顺序来比较两个字符串
    match() 找到一个或多个正则表达式的匹配
    replace() 替换与正则表达式匹配的子串
    search() 检索与正则表达式相匹配的值
    slice() 提取字符串的片断,并在新的字符串中返回被提取的部分
    split() 把字符串分割为子字符串数组
    substr() 从起始索引号提取字符串中指定数目的字符
    substring() 提取字符串中两个指定的索引号之间的字符
    toLocaleLowerCase() 根据主机的语言环境把字符串转换为小写,只有几种语言(如土耳其语)具有地方特有的大小写映射
    toLocaleUpperCase() 根据主机的语言环境把字符串转换为大写,只有几种语言(如土耳其语)具有地方特有的大小写映射
    toLowerCase() 把字符串转换为小写
    toString() 返回字符串对象值
    toUpperCase() 把字符串转换为大写
    trim() 移除字符串首尾空白
    valueOf() 返回某个字符串对象的原始值

(取自菜鸟教程)

总结几个我出过错的方法:

  1. .toString().valueOf()
    这两者的区别:

    • toString()和valueOf()的主要不同点在于,toString()返回的是字符串,而valueOf()返回的是原对象

    • 由于undefined和null不是对象,所以它们toString()和valueOf()两个方法都没有

    • 数值Number类型的toString()方法可以接收转换基数,返回不同进制的字符串形式的数值;而valueOf()方法无法接受转换基数。
      (这个“转换基数”我查了一下,指的是,对于不同进制之间的取值,比如:(19).toString(16) 的值是 "13";而 (19).valueOf(16) 的值还是19

    • 时间Date类型的toString()方法返回的表示时间的字符串表示;而valueOf()方法返回的是现在到1970年1月1日00:00:00的数值类型的毫秒数

    • 包装对象的valueOf()方法返回该包装对象对应的原始值

    • 使用toString()方法可以区分内置函数和自定义函数

  2. .exec() & .match():它们俩都是用来匹配的,不过前者是正则表达式的一个方法,方法可以作用于字符串,后者则相反。

  3. .slice() & .substring():这两个其实作用都是一样的,根据索引值截取字符串。不过有以下特殊情况

    var str = 'hello world';  
    str.slice(-3); // 'rld' 它会从后往前取|index|个字符  
    str.substring(-3); // 'hello world' 它会默认把负数转换成0  
    str.slice(1, -3); // 'ello wo' 这个时候,负数会转换成(string.length - |index|)  
    str.substring(1, -3); // ‘h’ 和前面一样,会将负数转换成0  
    //但是上面这个转换之后是 (1, 0),只有 substring 是可以取到字符串,slice 不行。
    str.slice(1, 0); // '' 
    //原因就是 substring 会将更小的索引值当成起始索引位置,而 slice 不行。
    
  4. .localeCompare()
    stringObject.localeCompare(target)
    返回比较结果的数字。如果 stringObject 小于 target,则 localeCompare() 返回小于 0 的数。如果 stringObject 大于 target,则该方法返回大于 0 的数。如果两个字符串相等,或根据本地排序规则没有区别,该方法返回 0。
    这里的大于 target 的比较方法是可以自己设定的,是没有被 ES 标准规定的,默认是按 Unicode 编码顺序的,可以和 .sort() 搭配起来给中英文排序,下面举个例子:

    let comparatorFun = (valueA, valueB) => {
      let targetA = valueA != null && valueA.toString().toLowerCase();
      let targetB = valueB != null && valueB.toString().toLowerCase();
      return targetA != null && targetA.localeCompare 
             ? targetA.localeCompare(targetB) : targetA - targetB;
    }
    
    let array=[1,9,0,'','我','他','我们']
    let sortArray = array.sort((a,b)=>comparatorFun(a,b)) //[ '', 0, 1, 9, '他', '我', '我们' ]
    
  • Number 对象
方法名 作用
valueOf() 返回数学对象的原始值
.toExponential(fractionDigits) 将数字转换为指数表示形式字符串,fractionDigits指定指数的小数位的位数, 取值区间[0,20].
.toFixed(fractionDigits) 将数字表示成10进制字符串, fractionDigits同上.
.toPrecision(precision) 与toFixed()类同, 只是precision指定的是数字的有效位数, 取值范围[0,21].
.toString(radix) 将number转换为需要的进制字符串形式,radix默认是10.

关于 .toFixed() 方法的一个小坑。
我们都知道这是一个四舍五入法保留 n 位小数的一个方法,但是当我们用于 1.toFixed(2) 的时候是会报 Uncaught SyntaxError: Invalid or unexpected token 的语法错误的。但是如果给 1 加上括号的话是成立的。后来是先查了一下这个方法的一个实现机制,它是先取小数点前的整数,然后再对后面的数进行处理大概这个样子。我们就觉得可能和小数点有关,之后我又查了一下,发现也有别人遇到过这个问题,并且总结了一下:

JS 引擎在运行时,默认将 .toFixed() 的点当作是 1.0 的点了,所以就觉得少了一个点,所以会报语法错误的。
解决的办法有很多种:

  1. 给无小数整数加一个括号,与后面的方法隔开。
  2. 在整数后面多加一个小数点即可。
  3. 将整数赋给一个变量,然后通过变量调用该方法。
  4. 给整数加零...

总之就是解决这个语法冲突而已,对于其他的方法,例如 .toString() 也是适用的。

  • Date 对象
方法名 作用
getDay() 返回一周中的第几天(0-6)
getYear() 返回年份.2000年以前为2位,2000(包含)以后为4位
getFullYear() 返回完整的4位年份数
getMonth() 返回月份数(0-11)
getDate() 返回日(1-31)
getHours() 返回小时数(0-23)
getMinutes() 返回分钟(0-59)
getSeconds() 返回秒数(0-59)
getMilliseconds() 返回毫秒(0-999)

这个对象的方法太多了,就不一一列举了,参考菜鸟教程

  • Array
    和 String 对象有些是类似的
方法 描述
concat() 连接两个或更多的数组,并返回结果。
copyWithin() 从数组的指定位置拷贝元素到数组的另一个指定位置中。
entries() 返回数组的可迭代对象。
every() 检测数值元素的每个元素是否都符合条件。
fill() 使用一个固定值来填充数组。
filter() 检测数值元素,并返回符合条件所有元素的数组。
find() 返回符合传入测试(函数)条件的数组元素。
findIndex() 返回符合传入测试(函数)条件的数组元素索引。
forEach() 数组每个元素都执行一次回调函数。
from() 通过给定的对象中创建一个数组。
includes() 判断一个数组是否包含一个指定的值。
indexOf() 搜索数组中的元素,并返回它所在的位置。
isArray() 判断对象是否为数组。
join() 把数组的所有元素放入一个字符串。
keys() 返回数组的可迭代对象,包含原始数组的键(key)。
lastIndexOf() 搜索数组中的元素,并返回它最后出现的位置。
map() 通过指定函数处理数组的每个元素,并返回处理后的数组。
pop() 删除数组的最后一个元素并返回删除的元素。
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reduce() 将数组元素计算为一个值(从左到右)。
reduceRight() 将数组元素计算为一个值(从右到左)。
reverse() 反转数组的元素顺序。
shift() 删除并返回数组的第一个元素。
slice() 选取数组的的一部分,并返回一个新数组。
some() 检测数组元素中是否有元素符合指定条件。
sort() 对数组的元素进行排序。
splice() 从数组中添加或删除元素。
toString() 把数组转换为字符串,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值。
  • RegExp 对象

    1. .test()

    test() 方法是一个正则表达式方法。
    test() 方法用于检测一个字符串是否匹配某个模式,如果字符串中含有匹配的文本,则返回 true,否则返回 false。
    例如: /e/.test("regex"); // true

    1. .exec()

    exec() 方法是一个正则表达式方法。
    exec() 方法用于检索字符串中的正则表达式的匹配。
    该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
    例如:/e/g.exec("The best things in life are free!"); // "e", index: 2

那这个和字符串的方法 .match() 有什么区别呢?
我们可以注意到,exec 方法的例子,明明用了全局匹配,却只匹配到了一个 "e",也就是第一个匹配到的那个。
那我们来看几种情况:

var str = "hellobell";
str.match(/ell/);
// ["ell", index: 1, input: "hellobell", groups: undefined]

str.match(/ell/g);
// (2) ["ell", "ell"]

/ell/.exec(str)
// ["ell", index: 1, input: "hellobell", groups: undefined]

/ell/g.exec(str)
// ["ell", index: 1, input: "hellobell", groups: undefined]

在没加全局匹配的时候,大家都是一样的,但加上全局的时候,只有 .match() 是有效的。

var p = /h(ell)/;

str.match(p);
// (2) ["hell", "ell", index: 0, input: "hellobell", groups: undefined]0: "hell"1: "ell"groups: undefined

p.exec(str)
// (2) ["hell", "ell", index: 0, input: "hellobell", groups: undefined]

var p = /h(ell)/g;

str.match(p);
// ["hell"]

p.exec(str)
// (2) ["hell", "ell", index: 0, input: "hellobell", groups: undefined]

这个时候是反过来的。

所以总结:

1) 当无g时,match的返回结果和exec是相同的,有无分组不受影响,当有g时,其将返回包含所有匹配项的数组。
2) 当有分组时,exec返回数组的第一个元素为匹配的完整串.后续元素为括号里捕获的字符串,当无分组时,只返回第一个匹配,g有没有都无影响。

这次先总结这么多,有不对的地方欢迎指出~

参考:JavaScript对象基础讲解

你可能感兴趣的:(JavaScript 对象基础)