10.5.JS-对象,包装类,原型,原型链,call/apply

233 阅读3分钟

1. 对象

  • 属性的增删改查
let person = {
  name: 'fun',
  age: 30,
  sex: 'male',
  health: 100,
  isSmoke: true,
  smoke: function () {
    console.log("I am smoking ");
    this.health--;
  },
  drink: function () {
    console.log("I am drinking");
    this.health++;
  },
  stopSmoke: function(){
    delete this.isSmoke;
  },
  addGame: function(){
    this.game = true;
  }
}
  • 对象的创建方法
    • 字面量
      • var obj = {}; plainObject 对象字面量/对象直接量
    • 构造函数
      • 系统自带 new Object(); Array(); Number(); Boolean(); String(); Date()
      • 自定义
          function Person(){
              
          }
          let person1 = new Person();
      
    • Object.create(原型)方法
      • 只有这个方法创建的对象可以没有构造函数,例:Object.create(null)
  • 构造函数内部原理
    1. 在函数体最前面隐式的加上 this={}
    2. 执行 this.xxx = xxx;
    3. 最后隐式返回this
      • 可以进行显式返回renturn {},返回值为对象会覆盖this,原始值不会覆盖this,this正常读取
function Person(name, height) {
  // var this = {}; // 在函数体最前面隐式的加上 `this={}`
  // 执行 `this.xxx = xxx;`
  this.name = name;
  this.height = height;
  this.say = function () {
    console.log(this.say())
  }
  // return this; // 最后隐式返回this
}
console.log(new Person('fun', 170).name); // fun

2. 包装类

  • new String(); new Boolean(); new Number();
  • 原始值不能有属性,但原始值可以读取属性,也可以对原始值进行属性添加,虽然无法使用,但不会报错
  • 原始值读取或添加属性不能使用undefined和null,会报错
    • 原理:每次对原始值进行属性添加,程序内部会先对原始值进行new Number('原始值')new String('原始值')new Boolean('原始值'), 变成对象后, 使用这个对象进行属性添加, 添加完后删除这个对象属性, 顺便也把属性删除了;每次对原始值进行属性读取, 程序内部也会对原始值进行对象实例化, 这个是系统自带的对象,所以只有系统自带的属性, 没有自定义的属性,非系统自带的属性,会返回undefined
  • 例子:
    1. 原始值添加属性原理
var str = 'fun';
str += 1;
var test = typeof (str); // 此时:test"string"
if (test.length == 6) {
  test.sign = "typeof的返回结果可能为String";
  // 隐式:对test进行new String(test).sign = 'xxx'; 然后删除这个对象属性
}
console.log(test.sign); // undefined 
2. this添加key-value
var a = 5;
function test() {
  a = 0;
  alert(a); 
  alert(this.a);
  var a;
  alert(a);
}
test(); // 0 5 0
new test(); // 0 undefined 0

3. 原型

  1. 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该对象的属性和方法。原型也是对象。
  2. 利用原型特点和概念,可以提取公共属性。
  3. 对象如何查看原型-->隐式属性 __proto__
  4. 对象如何查看对象的构造函数--> constructor
  • 原型是对象,所以修改原型属性更改对原型的引用,但直接换一个对象覆盖则不会影响原来的引用
Person.prototype.name = 'sunny';
function Person() {
  // var this = {__proto__ : Person.prototype}
}
var person = new Person();
Person.prototype = {
  name: 'cherry'
}
console.log(person.name); // "sunny"
// Person.prototype.name = 'cherry'
// console.log(person.name); // "cherry"

4. 原型链

  • 提取公共属性是根据原型链原理
Grand.prototype.LastName = 'fun';
function Grand() {

}
var grand = new Grand();

Father.prototype = grand;
function Father() {
  this.name = '腾';
}
var father = new Father();

Son.prototype = father;

function Son() {
  this.hobbit = "read";
}
var son = new Son();
// son.hobbit == "read" 
// son.__proto__.name == "腾" 
// son.__proto__.__proto__.LastName == son.__proto__.__proto__.constructor.prototype.LastName == "fun"
  • 方法的重用覆盖广泛存在在程序执行
    • js中对toString进行多次重写,使用 Object.prototype.toString().call('值') , 值为数组,打印 "[object Array]" , 值为{}, 打印 "[object Object]", 各个数据类型都对toString进行了重写, document.write隐式调用了toString

5. call/apply

  • this是谁调用便指向谁
  • call/apply可以改变this指向
  • call 需要把实参按照形参的个数传进去
  • apply 需要传一个arguments
// 造车
function Wheel(wheelSize, style) {
  this.wheelSize = wheelSize;
  this.style = style;
}
function Sit(c, sitColor) {
  this.c = c;
  this.sitColor = sitColor;
}
function Model(height, width, len) {
  this.height = height;
  this.width = width;
  this.len = len;
}
function Car(wheelSize, style, c, sitColor, height, width, len) {
  Wheel.call(this, wheelSize, style);
  Sit.call(this, c, sitColor);
  Model.call(this, height, width, len);
}
var car = new Car(100, 'cricle', null, 'black', 1800, 1900, 4900);

js计算有一定的问题,设计之初就存在的问题,计算不准确,时常出现计算失误; 在计算时,对数字进行向上向下取证,Math.floor() Math.ceil() js小数点前16位和后16位可正常计算