JavaScript高级程序设计 笔记 --- 3

创建对象的模式对比

/**
 * 工厂模式
 * 工厂模式虽然解决了创建多个相似对象的问题
 * 但却没有解决对象识别的问题
 *(即怎样知道一个对象的类型)。
 */
function createPerson(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;
  o.sayName = function(){
    alert(this.name);
  };
  return o;
} 
let person1 = createPerson('1',21,'test');
/**
 * 构造函数模式
 * 构造函数模式解决了上面工厂模式的问题【instanceof可以判断变量属于哪种类型】
 * 但是对于其中的function却是多次重复的,并不会重用,
 * 这样会造成性能与空间的浪费
 */
function Person(name,age,job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function(){
    alert(this.name);
  };
}
let person2 = new Person('1',21,'test');
/**
 * 原型模式
 * 原型模式可以做到function重用
 */
function PersonX(name,age,job){
  this.name = name;
  this.age = age;
  this.job = job;
}
PersonX.prototype.sayName = function(){
 alert(this.name);
};
let person3 = new PersonX('1222',21,'test');
person3.sayName(); //"1222" 

原型对象的理解

  • 只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。
  • 在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。
  • Example:Person.prototype.constructor 指向 Person。( function 也是一个对象 )。
  • 使用 Object.getPrototypeOf() 可以方便地取得一个对象的原型。( ES5的特性 )
  • 实例中的同名属性会覆盖对实例原型中的值的访问。当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性;换句话说,添加这
    个属性只会阻止我们访问原型中的那个属性,但不会修改那个属性。
  • 使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。

  • 遍历一个对象的所有可枚举属性可用Object.keys();

  • 遍历一个对象的所有实例属性可用Object.getOwnPropertyNames();
  • __Proto__指向的是父类对象的原型,new(或者说是实例化)出来的对象没有prototype这个属性,但是function是有的。
  • 通过给原生对象,可以添加新的自定义方法。
  • 通过 call 以及apply 的方法改变this的作用域,使子类能成功独立拥有父类的属性,而不会导致属性的共用。
// 测试代码
function Pers(age){ this.age = age; } let ttt = new Pers(21);  
Object.keys(ttt);
// >  ["age"]
Object.keys(ttt.__proto__);
// >  []
Object.keys(Pers.prototype);
// >  []
Pers.prototype.say = function(){ console.log(`hello, my age is ${this.age}`); }
ttt.say()
// >  hello, my age is 21
Object.keys(ttt.__proto__);
// >  ["say"]
Object.keys(Pers.prototype);
// >  ["say"]
ttt.say = () => { console.log('come on baby~');}
ttt.say();
// >  come on baby~
let uuu = new Pers(32);
uuu.say()
// >  hello, my age is 32

// 组合继承的参考代码
function SuperType(name){
 this.name = name;
 this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
 alert(this.name); 
};

function SubType(name, age){
 SuperType.call(this, name); //继承属性
 this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
 alert(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
let instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27 

JS间歇调用与延时调用

  • 间歇调用: let id_1 = setInterval(()=>console.log(1),1000); 间歇执行
  • 延时调用: let id_2 = setTimeout(()=>console.log(1),1000); 只延时执行一次
  • 使用clearInterval(id)来清除定时执行的任务

事件

  • 事件就是用户或浏览器自身执行的某种动作。
  • 事件流描述的是从页面中接收事件的顺序。事件流有2种,一种是冒泡,一种是捕获。
  • 冒泡:事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
  • 捕获:是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。
  • 对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值