美文网首页
Object 对象

Object 对象

作者: 麓语 | 来源:发表于2018-07-30 11:56 被阅读0次

上一篇:继承的概念
下一篇:Fountion 对象

主要内容:

  • Object 对象和其他对象的关系
  • Object 对象中已的⽅法
  • 字⾯量的类型
  • new 的含义

与其他⾯向对象的编程语⾔ ( Java, C# ) 类似, 可以说, JavaScript 中所有的对象都来⾃于 Object . 但是⼜不完全是这样. JavaScript 是利⽤原型来实现继承的. 为了弄清楚 JavaScript 的继承的本质, 接下来⾸先讨论⼀下 Object对象的⼀些细节.

Object 对象和其他对象的关系

要讨论 Object 对象与其他对象之间的关系, ⾸先来看对象的类型.

typeof 运算符和对象的类型

JavaScript 中, 数据类型分为基本类型和复合类型. 基本类型都有⾃⼰的类型名, 但是复合类型都被描述为 object. 可以使⽤ typeof 运算符加⼀验证.

console.log(typeof 123); // => number
console.log(typeof 1.23); // => number
console.log(typeof true); // => boolean
console.log(typeof "ly"); // => string
console.log(typeof []); // => object
console.log(typeof new Date()); // => object
console.log(typeof {}); // => object
console.log(typeof /./); // => object

原因很简单, 即使任何对象都直接或间接的继承⾃ Object.prototype 对象.

Object 的原型

了解到所有对象都直接或间接继承⾃ Object.prototype 后, 我们来理⼀理 ObjectObject.prototype 以及 其他对象之间的关系.

⾸先来看 Object 对象与 Object.prototype 的关系.

Object 对象与它的原型

先来看⼀段代码:

var o = new Object();
_ = null; // ⽤于设置断点调试

设置断点运⾏后:

Object 对象图1.png
可⻅由 Object 构造⽅法创建出来的对象没有任何成员.那些对象都共有的⽅法, 实际上都来源于 __proto__
Object 对象图2.png
暂时不管这些⽅法的含义. 这⾥ o.__proto__ 就是 Object.prototype . 因此他们之间的关系就很清楚了.
Object 对象图3.png
注意: __proto__ 并⾮标准属性.

其他对象的原型和 Object.prototype

了解了 Object 对象与其原型的关系后, 下⾯来看看⼀般对象与原型的关系, 以及⼀般对象与 Object.prototype 的关系.

function Person() {
}
Person.prototype.sayHello = function() {
  console.log("Hello, I'm JK!");
};
var p = new Person();
_ = null;

运⾏设置断点后:

Object 对象图4.png
可⻅其结构与 Object 对象和 Object.prototype 的结构⼀样. 然⽽原型对象也是有原型的, 虽然⽆法使⽤构造⽅法, 但是可以使⽤ __proto__ 来查看
Object 对象图5.png
从中可以发现⾃定义构造⽅法创建出来的对象 ( new <构造⽅法> )有⼀个原型对象, 即 <构造⽅法>.prototype . ⽽该原型对象也有原型对象. 根据图中可以看到原型对象的原型对象是 Object 类型的. 可⻅, ⾃定义构造⽅法创建对象的原型对象就是 Object 构造⽅法的实例.
Object 对象图6.png
从图中可以看出⾃定义对象和 Object 对象, 以及之间原型对象的关系.

内置对象

前⾯讨论了⾃定义对象, 接下来看看内置对象是否也复合这个关系.

⾸先看看数组:

var arr = [];
_ = null;

设上断点后运⾏


Object 对象图7.png

可以看到, 与⾃定义对象⼀致.

同理验证 Date 对象, Error 对象都是如此. 但是 Math 对象不同. Math 本⾝
是⼀个 Object 类型的对象.

Object 原型中定义的⽅法

接下来讨论 Object 原型对象中定义的⽅法.

var o = Object.prototype;
_ = null;

设定断点, 调试查看


Object 对象图8.png

可⻅原型对象中包含的都是⽅法:

  • __defineGetter__ ⽅法
  • __defineSetter__ ⽅法
  • __lookupGetter__ ⽅法
  • __lookupSetter__ ⽅法
  • constructor ⽅法
  • hasOwnProperty ⽅法
  • isPrototypeOf ⽅法
  • propertyIsEnumerable ⽅法
  • toLocaleString ⽅法
  • toString ⽅法
  • valueOf ⽅法
  • get __proto__ 读写器
  • set __proto__ 读写器

在这些⽅法中, 带有两个下划线开头和两个下划线结尾的⽅法是⾮标准⽅法.因此在部分浏览器中可能没有实现.

constructor ⽅法. 该⽅法即构造⽅法. 调⽤构造⽅法, 可以创建对象. 那么这个属性就是该对象构造⽅法的引⽤.

function Person() {}
var p = new Person();
console.log(typeof p.constructor); // => function
console.log(p.constructor === Person); // => true

hasOwnProperty ⽅法. 该⽅法需要⼀个字符串参数, ⽤来判断该字符串表⽰名字的属性是否为⾮继承属性. 如果是⾮继承属性, 就返回 true , 否则返回 false

function Person() {
  this.property1 = 1;
}
Person.prototype.property2 = 2;
var p = new Person();
console.log("p.property1 = " +
                p.property1 +
                ", hasOwnProperty = " +
                p.hasOwnProperty("property1"));
console.log("p.property2 = " +
                p.property2 +
                ", hasOwnProperty = " +
                p.hasOwnProperty("property2"));
console.log("p.toString = " +
                p.toString +
                ", hasOwnProperty = " +
                p.hasOwnProperty("toString"));

执⾏结果为

Object 对象图9.png
isPrototypeOf ⽅法. 如果目标对象是参数对象的原型对象, 那么就返回 true , 否则返回 false
function Person() {}
var p = new Person();
console.log(p.isPrototypeOf(p)); // => false
console.log(Person.prototype.isPrototypeOf(p)); // => true
console.log({}.isPrototypeOf(p)); // => false

propertyIsEnumerable ⽅法. 该⽅法需要⼀个字符串参数, 如果该字符串表⽰的名字是对象的⾃有属性, 同时该属性可枚举, 那么⽅法就会返回 true , 否则返回 false

function Person() {
  this.name = "jk";
}
Person.prototype.age = 10;
Object.prototype.gender = "男";
var p = new Person();
for (var k in p) {
  console.log(k + ", " + p[k] + ", " + p.propertyIsEnumerable(k));
}

执⾏结果为

Object 对象图10.png
实际上该⽅法与 hasOwnProperty ⽅法类似. 在 JavaScript 中只有⼀些内置的系统⽅法⽆法枚举. 因此该⽅法⼏乎总是返回 true . 但是在 ECMAScript 5 中给出了设置对象特性的⽅法, 可以设置某个属性是否可以枚举.

toString ⽅法和 toLocaleString ⽅法. 这两个⽅法都是将对象转换成字符串. 不同的是 toLocaleString 是转换为本地字符串. ⼀般对象与 toString⼀样. 但是时间类型不同.

var arr = [1,2,3];
console.log(arr.toString());
console.log(arr.toLocaleString());
var now = new Date();
console.log(now.toString());
console.log(now.toLocaleString());

执⾏结果为


Object 对象图11.png

valueOf ⽅法. 当对象需要转换为数字类型的时候就会调⽤该⽅法. 该⽅法与toString 类似.

var a1 = [1,2];
var a2 = [1,2];
a1.valueOf = function() {
  console.log("调⽤了 valueOf");
  return 3;
};
a1.toString = function() {
  console.log("调⽤了, toString");
  return "---";
};
console.log(Number(a1));
console.log(Boolean(a1));
console.log(String(a1));
console.log(Number(a2));

执⾏结果为


Object 对象图12.png

⾄于 getset 以及带有两个下划线的⽅法, 后⾯再详细说明.

字⾯量的类型

在实际开发中, 由于字⾯量不需要定义构造⽅法, 也不需要 new 等操作. 因此字⾯量的效率会⽐较⾼, 因此尽量使⽤对象的字⾯量. 但是, 没有构造⽅法, 也就表明⽆法实现复⽤. 因此选择需要权衡.

那么字⾯量的类型是什么呢? 还是利⽤调试来进⾏查看

var o = {};
_ = null;

设断点后:

Object 对象图13.png
可⻅对象的字⾯量是 Object 类型的. 它的原型就是 Object.prototype

new 以及构造函数的执⾏过程

除了字⾯量以外, 对象也可以使⽤ new 构造函数的形式被创建出来. 使⽤构造函数与使⽤对象字⾯量的最⼤区别在于, 使⽤构造⽅法可以复⽤, 利⽤构造⽅法可以创建出多个对象; 但是使⽤对象的字⾯量, 只会有⼀个对象.
那么构造函数具体做了什么, 下⾯来进⾏说明.

function Person(name, age, gender) {
  this.name = name;
  this.age = age;
  this.gender = gender;
}
var p = new Person("jk", 19, "m");

这⾥定义了构造函数 Person , 然后调⽤构造⽅法, 创建了⼀个对象 p
代码 var p = new Person("jk", 19, "m"); 可以分成三个步骤:
1, 执⾏ new 关键字, 开辟内存控件, 闭关获得内存引⽤
2, 调⽤构造⽅法 Person , 传递参数: 内存引⽤, 字符串 "jk" , 数字 19 , 和字符串 "m" (m 表⽰男, f 表⽰⼥)
3, 执⾏完构造⽅法, 将地址引⽤返回给左边的变量 p

上一篇:继承的概念
下一篇:Fountion 对象

⼩结

  • 所有的对象都继承⾃ Object.prototype
  • Object.prototype 中常⻅的⽅法有:
    constructor ⽅法
    hasOwnProperty ⽅法
    isPrototypeOf ⽅法
    propertyIsEnumerable ⽅法
    toLocaleString ⽅法
    toString ⽅法
    valueOf ⽅法
  • 对象字⾯量是 Object 类型的对象
  • new 关键字开辟内存空间
  • 构造⽅法调⽤隐含参数 this

相关文章

网友评论

      本文标题:Object 对象

      本文链接:https://www.haomeiwen.com/subject/emzxvftx.html