《JavaScript标准参考教程(alpha)》读书笔记一:面向对象编程

1.概述

原文地址

js基于构造函数(constructor)和原型链(prototype)

构造函数:

作用:提供模板,描述对象的基本结构

var Vehicle=function(a){
    this.price=a;
}
  1. 函数体内部使用了this
  2. 生成对象时必须使用new命令
  3. 为表示区别,第一个字母通常大写

new:

作用:执行构造函数,返回一个实例对象

var v=new Vehicle();    //也可不带括号
  1. 忘记使用new命令直接调用构造函数

    var v=Vehicle();
    v.price        //v变成了undefined
    price      //price为全局变量
  2. 为避免这种情况,可以在构造函数内部第一行加上"use strict"(严格模式下this不能指向全局对象,默认等于undefined,由于不能对undefined添加属性,导致不加new调用会报错);
    另外还可以在构造函数内部加一个判断

    if(!(this instanceof 函数名)){
        return new 函数调用;
    }
  3. 如果构造函数内部有return语句,若return返回一个数值,new命令会忽略return语句,返回构造后的this对象。

  4. 如果返回的是一个与this无关的新对象,new命令返回新对象不返还this对象
  5. 若对普通函数(内部没有this关键字)使用new命令,会返回一个空对象

new的原理:

  1. 创建一个空对象
  2. 把空对象的原型指向构造函数的prototype属性
  3. 把空对象赋值给函数内部的this关键字
  4. 开始执行构造函数内部代码

2.this关键字

原文地址

this总是返回属性或方法当前所在的对象(比如在setTimeout()的回调函数中使用this会指向它所在的对象window),this指向可人为改变,函数在全局环境下运行时this指向顶层对象window
详见原文

绑定this:

方法用法
function.prototype.call(obj[,arg1,arg2,...])f内部的this指向obj,若参数为空、null、undefined,默认传入全局对象,若参数是一个原始值(如5等),则这个原始值自动转成对应的包装对象(如Number的实例),可以在覆盖掉继承的方法后,用call来调用对象的原生方法
function.prototype.apply(obj[, [arg1, arg2, ...]])与call类似,但是——如果要传入参数,必须以数组形式传入,应用见原文,一定要见!
function.prototype.bind(obj[,arg1,arg2,...])比call和apply更进一步,不仅可以绑定this,还可以绑定原函数的参数,每一次运行都会返回一个新函数,这些话不懂的话见原文,注意事项也要见原文,一定要见!

3.Object对象与继承

原文地址

各种方法:

方法用法
Object.getOwnPropertyNames(obj)数组形式返回obj本身的所有属性的键名(不包括继承的属性)
Object.keys(obj)与上面的类似,但是只返回可枚举的属性键名
Object.prototype.hasOwnProperty('属性名')返回一个Boolean值,判断某个属性定义在对象自身还是原型链上,是js中唯一一个处理对象属性时不会遍历原型链的方法

in运算符和for…in循环:

/示例用法
in'属性名' in obj返回一个Boolean值,表明obj是否具有该属性,不区分是否是继承来的属性
for...in暂时不明获取对象的所有可枚举属性,不区分是否继承而来,详情见原文

对象的拷贝:

见原文

4.prototype 对象

原文地址
真正理解prototype

概述:

  1. JavaScript的每个对象都继承另一个对象,后者称为“原型”(prototype)对象。null除外,它没有自己的原型对象。
  2. 通过构造函数生成实例对象时,会自动为实例对象分配原型对象。每一个构造函数都有一个prototype属性,这个属性就是实例对象的原型对象。当实例对象本身没有某个属性或方法的时候,它会到构造函数的prototype属性指向的对象,去寻找该属性或方法。总结一下,原型对象的作用,就是定义所有实例对象共享的属性和方法。
  3. 原型对象上的所有属性和方法,都能被派生对象共享。这就是JavaScript继承机制的基本设计。

构造函数的缺陷:

实例之间不能共享属性,如果在构造函数中定义this.func: ...,每新建一个实例就新建一个方法,没有必要且浪费系统资源;

原型链:

  1. 对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。所有对象的原型最终都可以上溯Object.prototype;
  2. Object.prototype的原型就是没有任何属性和方法的null对象,null对象没有自己的原型。
    详情见原文

constructor属性:

prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。
修改了prototype以后,constructor属性的指向就变了,导致instanceof运算符失真。所以,修改原型对象时,一般要同时校正constructor属性的指向。

// 避免这种写法
C.prototype = {
  method1: function (...) { ... },
  // ...
};

// 较好的写法
C.prototype = {
  constructor: C,
  method1: function (...) { ... },
  // ...
};

// 好的写法
C.prototype.method1 = function (...) { ... };

此外,通过name属性,可以从实例得到构造函数的名称,如:f.constructor.name

instanceof运算符:

  1. instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。
  2. 由于instanceof对整个原型链上的对象都有效,因此同一个实例对象,可能会对多个构造函数都返回true。
  3. instanceof的原理是检查原型链,对于那些不存在原型链的对象,就无法判断。
  4. instanceof运算符只能用于对象,不适用原始类型的值。

各种方法:

方法用法
Object.getPrototypeOf(obj)返回一个对象的原型
Object.setPrototypeOf(现有obj,原型对象)为现有对象设置原型,返回一个新对象
Object.create(obj)用于从原型对象生成新的实例对象,生成的新对象动态继承了原型。在原型上添加或修改任何方法,会立刻反映在新对象之上
Object.prototype.isPrototypeOf()对象实例的isPrototypeOf方法,用来判断一个对象是否是另一个对象的原型。

Object.create()的其他用法:

除了对象的原型,Object.create方法还可以接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到新对象。只要某个对象处在原型链上,isProtypeOf都返回true。

var o = Object.create({}, {
  p1: { value: 123, enumerable: true },
  p2: { value: 'abc', enumerable: true }
});

// 等同于
var o = Object.create({});
o.p1 = 123;
o.p2 = 'abc';

Object.prototype._proto_

__proto__属性可以改写某个对象的原型对象。

5.面向对象编程的模式

原文地址

暂时不写了,见原文吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值