ES6(2)构造函数和原型、对象

创建对象的方法

// 使用new Object创建对象
let obj = new Object();
// 使用对象字面量创建对象
let obj2 = {};
//  使用构造函数创建对象
function Star(username, age) {
  this.username = username;
  this.age = age;
  this.sing = function() {
    console.log("song");
  };
}

let p = new Star("jack", 19);
p.sing();
实例成员和静态成员

//  使用构造函数创建对象
function Star(username, age) {
  // 构造函数内部通过this添加的成员,称为实例成员,只能通过实例化的对象来访问
  this.username = username;
  this.age = age;
  this.sing = function() {
    console.log("song");
  };
}

let p = new Star("jack", 19);
p.sing();
// 在构造函数本身添加的成员就是静态成员
Star.sex = "男";
// 只能通过构造函数来访问,不能通过对象来访问
console.log(Star.sex);
构造函数存在浪费内存的问题

构造函数通过原型分配的函数式所有对象共享的,这个对象的所有属性和方法,都会被构造函数所拥有。

把不变的方法直接定义在prototype对象上,所有的对象的实例就可以共享这些方法

function Star(username, age) {
  // 公共属性定义到构造函数里
  this.username = username;
  this.age = age;
}
// 公共方法放到原型对象上
// Star.prototype.sing = function() {
//   console.log("song");
// };
// Star.prototype.movie = function() {
//   console.log("movie");
// };
Star.prototype = {
  // 如果修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动指向原来的构造函数
  constructor: Star,
  sing: function() {
    console.log("song");
  },
  movie: function() {
    console.log("movie");
  }
};
// 对象都会有一个__proto__指向构造函数的prototype原型对象,
// 对象之所以能够使用构造函数的prototype原型对象的方法,就是因为有__proto__原型的存在。
// 虽然没有定义p对象的方法,但是系统自动为p对象身上添加__proto__指向构造函数的原型对象。
let p = new Star("jack", 19);
// 方法查找规则:首先查找p对象有没有sing方法,有就执行sing方法,没有就去构造函数原型上查找sing方法
p.sing();
// console.dir(Star);
// console.log(p.__proto__ === Star.prototype);
console.log(Star.prototype.constructor);
console.log(p.__proto__.constructor);
console.log(Star.prototype);
console.log(p.__proto__);
原型链

function Star(username, age) {
  this.username = username;
  this.age = age;
}
Star.prototype.sing = function() {
  console.log("song");
};
let p = new Star("jack", 19);
// 只要是对象就有有__proto__原型,指向原型对象
console.log(Star.prototype);
// 在Star原型对象里面的__proto__原型指向的是Object.prototype
console.log(Star.prototype.__proto__ === Object.prototype);
// Object.prototype原型对象里的__proto__原型指向为null
console.log(Object.prototype.__proto__);
对象成员查找规则

function Star(username, age) {
  this.username = username;
  this.age = age;
}
Star.prototype.sing = function() {
  console.log("song");
};
// Star.prototype.sex = "man";
Object.prototype.sex = "woman";
let p = new Star("jack", 19);
p.sex = "man";
// 访问对象的属性和方法时,(就近原则)先查找对象自身有没有该属性,没有就找prototype原型对象上的,再没有就找Object的原型对象
console.log(p.sex);
原型对象this指向

// 在构造函数中,里面的this指向的是实例对象p
function Star(username, age) {
  this.username = username;
  this.age = age;
}
let that;
Star.prototype.sing = function() {
  console.log("song");
  that = this;
};
let p = new Star("jack", 19);
p.sing();
// 原型对象函数里的this指向的是实例对象p
console.log(that === p); // true
利用原型对象扩展内置对象方法

Array.prototype.sum = function() {
  let sum = 0;
  for (let i = 0; i < this.length; i++) {
    sum += this[i];
  }
  return sum;
};
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.sum());
console.log(Array.prototype);
call 调用这个函数,并修改函数运行时的this指向

function fn(x, y) {
  console.log("hello");
  // 指向window
  // console.log(this);
  console.log(x + y);
}
let o = {
  name: "andy"
};
// 1. call()可以调用函数
// fn.call();
// 2. 改变这个函数的this指向,在函数里面指向了o这个对象,并传递了参数
fn.call(o, 1, 2);
借用父构造函数来继承属性和方法

// 借用父构造函数来继承属性
function Father(username, age) {
  // 里面的this指向的是父构造函数的对象实例
  this.username = username;
  this.age = age;
}
Father.prototype.money = function() {
  console.log("money");
};
function Son(username, age, score) {
  // 里面的this指向的是子构造函数的对象实例,使用call之后,父构造函数里面的this变成了子函数里的this
  Father.call(this, username, age);
  this.score = score;
}
// 继承Father的方法,但不会影响Father类
Son.prototype = new Father();
// 如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的构造函数
Son.prototype.constructor = Son;
// 子构造函数的独有方法,不会改变影响父类
Son.prototype.exam = function() {
  console.log("exam");
};
let p = new Son("jack", 19, 100);
p.money();
p.exam();
console.log(p);
console.log(Father.prototype);
console.log(Son.prototype.constructor);
类的本质
其实还是一个function

class Star {}
console.log(typeof Star); // function
Foreach

let arr = [1, 2, 3];
let sum = 0;
arr.forEach((value, index, array) => {
  // console.log("每个数组元素", value);
  // console.log("每个数组元素的索引号", index);
  // console.log("数组本身", array);
  sum += value;
});
console.log(sum);
filter

let arr = [32, 18, 78, 40, 11, 13];
// filter遍历,通过筛选返回一个新的数组
let temp = arr.filter((value, index) => {
  // return value >= 20;
  return value % 2 === 0;
});
console.log(temp);
some

let arr = [32, 18, 78, 40, 11, 13];
// some 查找数组中是否有满足条件的元素(数组当前项的值,索引,数组本身),
// 返回一个布尔值,如果找到就返回为true,找到第一个满足的就终止循环
let flag = arr.some((currentValue, index, arr) => {
  // return currentValue % 2 === 0;
  return currentValue > 100;
});
console.log(flag);

filter  some区别

filter查找满足的元素,返回一个数组,把所有满足的元素返回来

some查找满足的元素,返回一个布尔值,找到第一个就终止

trim

let str = "  2  2  4  ";
console.log(str.trim());
console.log(str.trimStart());
console.log(str.trimLeft());
Object.defineProperty

let obj = {
  id: 1,
  name: "jack",
  age: 19
};
/**
 * obj 目标对象  prop 需定义或修改属性的名字  descriptor 目标属性所拥有的特性
 * Object.defineProperty(obj, prop, descriptor);
 * **/
// 修改存在的属性
Object.defineProperty(obj, "age", {
  value: 20
});
// 是否允许修改属性值,默认为false
Object.defineProperty(obj, "id", {
  writable: true
});
obj.id = 2;
// 没有就是新增属性,定义一个num的属性,值为1000
Object.defineProperty(obj, "num", {
  value: 1000,
  // 是否可以重写,默认为false
  writable: false,
  // enumerable为false,则不会被枚举,默认值是false
  enumerable: false,
  // configurable 目标属性是否可以删除或再次修改,默认为false
  configurable: false
});
console.log(obj); // {id: 2, name: "jack", age: 20, num: 1000}
console.log(Object.keys(obj)); // ["id", "name", "age"]
delete obj.num;
console.log(obj); // num 不可被删除
// 上面设置了num不可被再次定义,所以再次修改就不可以了
Object.defineProperty(obj, "num", {
  value: 1000,
  writable: true,
  enumerable: true,
  configurable: true
});
Object.keys()

let obj = {
  id: 1,
  name: "jack",
  age: 19
};
/**
 * Object.keys()获取对象自身所有的属性
 * 类似于for..in
 * 返回一个由属性名组成的数组
 * **/
let arr = Object.keys(obj);
// 遍历属性名
arr.forEach(value => {
  console.log(value);
});
    let myData = [
      {
        name: "公告区",
        todayposts: "0",
        fid: "2"
      },
      {
        name: "产品动态",
        todayposts: "0",
        fid: "58"
      },
      {
        name: "专区",
        todayposts: "0",
        fid: "72"
      },
      {
        name: "公告",
        todayposts: "0",
        fid: "73"
      }
    ];
    Object.keys(myData).map(key => {
      console.log(myData[key]);
    });

 

Object.assign

let obj = {};
// 浅拷贝
let obj2 = Object.assign(obj, { name: "jack" }, { age: 19 });
// console.log(obj2);
// 得到自身可枚举属性,得不到原型链上的属性
console.log(Object.keys(obj2));
// 得到自身属性,包括不可枚举的属性,得不到原型链上的属性
console.log(Object.getOwnPropertyNames(obj2));
proxy

let obj = {
  time: "2000-01-01",
  name: "tom"
};
let monitor = new Proxy(obj, {
  // 拦截对象属性的读取
  get(target, key) {
    return target[key].replace("2019", "2020");
  },
  // 拦截对象设置属性
  set(target, key, value) {
    // 只有key等于name才修改
    if (key === "name") {
      return Reflect.set(target, key, value);
    } else {
      return target[key];
    }
  },
  // 拦截 key in object操作
  has(target, key) {
    if (key === "name") {
      return target[key];
    } else {
      return false;
    }
  },
  // 拦截delete
  deleteProperty(target, key) {
    if (key.indexOf("-")) {
      delete target[key];
      return true;
    } else {
      return target[key];
    }
  },
  // 拦截Object.keys
  // Object.getOwnPropertySymbols
  // Object.getOwnPropertyNames
  ownKeys(target) {
    return Object.keys(target).filter(item => item !== "time");
  }
});
// 2020-01-01
console.log("get", monitor.time);
monitor.time = "2030";
monitor.name = "kaka";
// 只有name被修改  kaka
console.log("set", monitor, monitor.name);

console.log("has", "name" in monitor, "time" in monitor);
// // 删除掉日期
// delete monitor.time
// console.log('delete', monitor)

// 返回不等于key不等于time的元素
console.log("ownKeys", Object.keys(monitor));
Reflect

// Reflect 跟proxy代理类似,方法属性都一样
let obj = {
  time: "2019-01-01",
  name: "ronle"
};
console.log(Reflect.get(obj, "time"));
Reflect.set(obj, "name", "kaka");
console.log(obj);
console.log(Reflect.has(obj, "name"));

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值