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

来源:互联网 发布:java类的定义 编辑:程序博客网 时间:2024/05/17 02:38

1.概述

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

构造函数:

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

var Vehicle=function(a){    this.price=a;}

函数体内部使用了this
生成对象时必须使用new命令
为表示区别,第一个字母通常大写

new:

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

var v=new Vehicle();    //也可不带括号

忘记使用new命令直接调用构造函数
var v=Vehicle();
v.price //v变成了undefined
price //price为全局变量

为避免这种情况,可以在构造函数内部第一行加上use strict,严格模式下this不能只想全局对象,默认等于undefined,由于不能对undefined添加属性,导致不加new调用会报错;
另外还可以在构造函数内部加一个判断if(!(this instanceof 函数名)){
return new 函数调用;
}

如果构造函数内部有return语句,若return返回一个数值,new命令会忽略return语句,返回构造后的this对象。
如果返回的是一个与this无关的新对象,new命令返回新对象不返还this对象

若对普通函数(内部没有this关键字)使用new命令,会返回一个空对象

new的原理:

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

2.this关键字

原文地址
this总是返回属性或方法当前所在的对象,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 对象

原文地址

概述:

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

原型对象上的所有属性和方法,都能被派生对象共享。这就是JavaScript继承机制的基本设计。

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

原型链:
对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)。所有对象的原型最终都可以上溯Object.prototype,Object.prototype的原型就是没有任何属性和方法的null对象,null对象没有自己的原型,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运算符:

instanceof运算符返回一个布尔值,表示指定对象是否为某个构造函数的实例。
由于instanceof对整个原型链上的对象都有效,因此同一个实例对象,可能会对多个构造函数都返回true。
instanceof的原理是检查原型链,对于那些不存在原型链的对象,就无法判断。
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.面向对象编程的模式

原文地址
暂时不写了,见原文吧

0 0
原创粉丝点击