Javascript |(五)对象

标准对象

在JavaScript的世界里,一切都是对象。

typeof 123; // 'number'
typeof NaN; // 'number'
typeof 'str'; // 'string'
typeof true; // 'boolean'
typeof undefined; // 'undefined'
typeof Math.abs; // 'function'
typeof null; // 'object'
typeof []; // 'object'
typeof {}; // 'object'

  

包装对象

有以下几点需要遵守。

  • 可用通过String()或者调用对象的toString()方法把任何对象转换成String,但是不是所有对象都有toString方法:nullundefined就没有。同时将数字转换成String要使用如下的形式。
123..toString();
(123).toString();
  • parseInt()或者parseFloat()将任意类型的对象转换成Number
  • 没事不要用包装对象,特别是String
  • 判断ArrayisArray(arr)
  • obj === null来判断null
      

Date

获得不同形式的系统的时间。注意月份是以0开始的。

var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范围是0~11,5表示六月
now.getDate(); // 24, 表示24号
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小时制
now.getMinutes(); // 49, 分钟
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒数

显示本地时间。

var d = new Date(1435146562875);
d.toLocaleString(); // '2015/6/24 下午7:49:22',本地时间(北京时区+8:00),显示的字符串与操作系统设定的格式有关
d.toUTCString(); // 'Wed, 24 Jun 2015 11:49:22 GMT',UTC时间,与本地时间相差8小时

时间戳是个什么东西?时间戳是一个自增的整数,它表示从1970年1月1日零时整的GMT时区开始的那一刻,到现在的毫秒数。
假设浏览器所在电脑的时间是准确的,那么世界上无论哪个时区的电脑,它们此刻产生的时间戳数字都是一样的,所以,时间戳可以精确地表示一个时刻,并且与时区无关。
所以,我们只需要传递时间戳,或者把时间戳从数据库里读出来,再让JavaScript自动转换为当地时间就可以了。
获取当前的时间戳的方法如下。

Date.now()
new Date.getTime();

  

JSON

JSON是JavaScript Object Notation的缩写,它是一种数据交换格式。
他设计的JSON实际上是JavaScript的一个子集。在JSON中,一共就这么几种数据类型:

  • number:和JavaScript的number完全一致;
  • boolean:就是JavaScript的true或false;
  • string:就是JavaScript的string;
  • null:就是JavaScript的null;
  • array:就是JavaScript的Array表示方式——[];
  • object:就是JavaScript的{ … }表示方式。

并且,JSON还定死了字符集必须是UTF-8,表示多语言就没有问题了。为了统一解析,JSON的字符串规定必须用双引号"",Object的键也必须用双引号""。
把任何JavaScript对象变成JSON,就是把这个对象序列化成一个JSON格式的字符串,这样才能够通过网络传递给其他计算机。

const obj = {
   name: 'jim',
   age: 10,
   single: true
}
JSON.stringify(obj);
JSON.stringify(obj, null, ' ');
JSON.stringify(obj, ['name', 'age']);
JSON.stringify(obj, (key, value) => typeof value === 'string' ? value.toUpperCase() : value);

可以通过toJSON方法做到更加精确的控制。

const obj = {
   name: 'jim',
   age: 10,
   single: true,
   toJSON: () => {
      return {
        Name: this.name,
        Age: this.age
      }
   }
}
JSON.stringify(obj);

  

面向对象编程

创建对象

  • Student是一个对象的构造函数,该函数用new的时候返回一个对象,并且把该函数作为该对象的constructor。如果不用new,在严格模式下会报错,因为this.nameundefined;在非严格模式下,该name会绑定到全局变量上。
  • 构造函数中的成员变量和函数都是该对象独有的,如果希望节省内存的话,可以将共有的变量和方法定义在构造函数的原型链上(对象的原型)。可以说s1s2都是继承自Student
  • 原型链为:s1 ----> Student.prototype ----> Object.prototype ----> null
  • 对象可以通过__proto__属性获得它继承的对象,构造函数可以通过prototype获得它的对象原型。
  • Object, Numer, String, Boolean这些都是构造函数,不是对象本身。
  • Number, String, Boolean, Array, Map这些对象都是继承自Object对象。
    在这里插入图片描述
function Student(name, age){
  this.name = name;
  this.age = age;
  this.printName = function(){
    console.log(`My name is ${this.name}.`);
  }
}

Student.prototype.printAge = function(){
  console.log(`My age is ${this.age}.`);
}

Student === Student.prototype.constructor // true
Object === Object.prototype.constructor // true
Student.prototype.prototype // undefined
Student.prototype.__proto__ === Object.prototype // true
Number.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ // null
typeof Object // function
const s1 = new Student('jim', 10),
      s2 = new Student('peter', 12);
      
s1.constructor === Student // true
s1.printName === s2.printName // false
s1.printAge === s2.printAge // true
s1.prototype // undefined
s1.__proto__ === Student.prototype // true

下面是一种比较好的创建对象的方法。

function Student(props){
  this.name = props.name || 'jim';
  this.age = props.age || 1;
}

Student.prototype.hello = function(){
	console.log(`My name is ${this.name}.`)
};

function createStudent(props){
  return new Student(props || {});
}

  

原型继承

  下面来看一下js中通过原型链继承,如果希望Dog继承自Animal,那么目标就是Dog.prototype.__proto__ === Animal.prototype。所以最简单和最好想的方法如下。

function Animal(){};
function Dog(){};
Dog.prototype.__proto__ = Animal.prototype;

const d = new Dog();
d instanceof Animal // true;

  但是这种动态设置原型会大大影响浏览器的执行效率。
  如果你在生产环境中使用这个方法,那么快速运行 Javascript 就是不可能的,因为许多浏览器优化了原型,尝试在调用实例之前猜测方法在内存中的位置,但是动态设置原型干扰了所有的优化,甚至可能使浏览器为了运行成功,使用完全未经优化的代码进行重编译。
  所以应该摈弃这中行为。
  下面是另外一种方法。

function Animal(){};
function Dog(){};
function inherits(Child, Parent){
  Child.prototype = new Parent();
  Child.prototype.constructor = Child;
}
inherits(Dog, Animal);

const d = new Dog();
d instanceof Animal // true;

  这种方法看似可行,但是有一个问题,就是再改变原型链的时候调用了父亲类的构造函数,并且没有传入任何参数,这很可能出现问题。所以最好的方法应该是成员变量和成员函数分开继承。

function Animal(name){
  this.name = name;
};
function Dog(name){
  Animal.call(this, name);
};
function inherits(Child, Parent){
  const F = function(){};
  F.prototype = Parent.prototype;
  Child.prototype = new F();
  Child.prototype.constructor = Child;
}
inherits(Dog, Animal);

const d = new Dog('Dog');
d instanceof Animal // true;
d.name // Dog

  

Class

  在ES6中多了Class,就可以非常方便的创建和继承对象了。

class Animal{
  constructor(name){
    this.name = name;
  }
  
  hello(){
    console.log('hello world');
  }
}

class Dog extends Animal{
  constructor(name, age){
    super(name);
    this.age = age;
  }
}

const d = new Dog('Dog');
d.name // 'Dog'
d.hello() // 'hello world'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值