JS基础:基于原型的对象系统

简介:

  仅从设计模式的角度讲,如果我们想要创建一个对象,一种方法是先指定它的类型,然后通过这个类来创建对象,例如传统的面向对象编程语言 "C++"、"Java" 等;另一种方式是,我们不需要关心对象的具体类型,而是找到一个对象,然后通过克隆来创建一个一模一样的对象,就像所有吸血鬼故事必然有一个吸血鬼祖先一样,在 "Javascript" 世界中 "Object" 对象就是这个吸血鬼祖先,所有其他对象都是继承自 "Object" 对象来的,如果 A 对象继承自 B 对象,那么 B 对象就是 A 对象的原型。

在基于原型的对象系统中,至少包含以下规则:

(1) 一切皆对象

(2) 要创建一个对象不是通过实例化类,而是找到一个对象作为原型并克隆它

(3) 对象会记住它的原型

(4) 如果对象无法响应某个请求,它会把这个请求委托给它自己的原型 (原型链)

创建对象:

  在 JS 中有三种创建对象的方式:通过对象字面量、通过构造函数、通过 Object.create() 函数。

//示例一:通过对象字面量创建对象
var boy = {
  name: ‘Bob‘,
  sex: ‘male‘
}
//示例二:通过构造函数创建对象
function Person(name, sex) {
  this.name = name;
  this.sex = sex;
}
var boy = new Person(‘Bob‘, ‘male‘);
//示例三:通过 Object.create() 函数创建对象
var boy1 = {
  name: ‘Bob‘,
  sex: ‘male‘
}
var boy2 = Object.create(boy1);

一切皆对象

  事实上,在 JS 中并非一切皆对象,这只是一种笼统的说法,由于 JS 引入了两种数据类型:基本类型 ( Undefind、 Null、 Boolean、 Number 和 String ) 和对象类型 ( Object 、Function),对象类型是对象自然不必多说,问题在于基本类型是对象吗?我们先上字符串类型来说明一下:

var str = ‘Make life better‘;
console.log(str.length);        //输出 16

按理说 "str" 变量只是一个字符串,但是它却使用了对象才有的 "length" 属性,输出了字符串的长度,因此这里我们有理由把字符串类型看成对象,称为 "包装对象"。这个对象是临时的,也就是说只有在读取它的属性的时候 JS 才会把这个字符串通过 new String() 方式创建成一个字符串对象,一旦引用结束这个对象就被销毁了,换句话说 "包装对象" 的属性是 "只能读,不能写" 的。同理 "Boolean" 和 "Number" 在读取属性的时候也可以通过自己的构造函数来创建自己的一个包装对象,并像对象一样引用各自的属性。

其次,"null" 表示 "空值",对 "null" 执行 "typeof" 操作,输出结果为 "Object",所以我们也可以把 "null" 看成一个对象,称为 "空对象"

最后,"undefind" 表示 "未定义",当我们对变量只声明没有初始化时,输出 "undefind",或者引用一个不存在的属性时,输出也为 "undefind",对 "undefind" 执行 "typeof" 操作的输出结果为 "undefind",这么说来 "undefind" 其实并不属于对象范畴

要创建一个对象不是通过实例化类,而是找到一个对象作为原型并克隆它

  在 JS 中,"Object.prototype" 是所有对象的原型,我们并不需要关心克隆的细节,因为这是引擎内部负责实现的。我们所需要做的只是显式地调用 var obj1 = {}; 或者 var obj2 = new Object(),此时,引擎内部会从 "Object.prototype" 上面克隆一个对象出来,作为新对象的原型。

示例一:

var obj1 = {};
var obj2 = new Object();
console.log(Object.getPrototypeOf(obj1) === Object.prototype); //输出true
console.log(obj2.__proto__ === Object.prototype); //输出true

每个对象都具有 "__proto__"(前后两个下划线) 属性,它指向该对象的原型,但是它只是一个内部属性,而不是一个正式的对外 API,原则上是不能访问的,这是由于很多浏览器的支持,才把这个属性暴露出来了。在ES5中使用 "Object.getPrototypeOf()" 获取一个对象的原型,在ES6中可以使用 "Object.setPrototypeOf()" 设置一个对象的原型。因此,在这里两者的作用都是一样的,都是获取对象的原型,并且它们的原型都是 "Object.prototype"。

只有函数才有 "prototype" 属性,例如 "Object.prototype",对于函数而言,"__proto__" 属性指向它的原型, "prototype" 属性则是通过这个函数构造出来的对象的原型,可以理解为这样一条原型链,"__proto__" 总是指向原型链的顶端,而函数恰好可以延长原型链,于是它将自己 "prototype" 属性指向的对象压入原型链的顶端,自然它构造出来的对象的 "__proto__" 属性就指向了它自己的 "prototype"。

示例二:

function Person(name, sex) {
  this.name = name;
  this.sex = sex;
}
var boy = new Person(‘Bob‘, ‘male‘);
console.log(Object.getPrototypeOf(Person) === Function.prototype); //true
console.log(Object.getPrototypeOf(boy) === Person.prototype); //true

Person 函数继承自 Function 对象,如果这么写就很直观了:

var Person = new Function(‘name‘, ‘sex‘, ‘this.name = name;this.sex = sex;‘);

因此 Person 函数的原型指向 Function.prototype,boy 对象是通过 Person 函数构造而来的,因此它的原型指向 Person.prototype。

对象会记住它的原型

  上面已经提到,JS 给所有对象提供了一个 "__proto__" 属性,用于访问它的原型

如果对象无法响应某个请求,它会把这个请求委托给它自己的原型

示例:

function A() {}
A.prototype = { name: ‘better‘ };
var a = new A();
a.name = ‘bett‘;
function B() {}
B.prototype = a;
var b = new B();
console.log(b.name); //输出bett

b 对象本身没有 "name" 属性,于是在它的原型,即构造函数的 "prototype" 中去找,a 对象有 "name" 属性,于是停止上溯,输出bett。

原文地址:https://www.cnblogs.com/blog-cxj2017522/p/8992138.html

时间: 2024-10-12 14:14:00

JS基础:基于原型的对象系统的相关文章

JS基础语法---内置对象

js学习中三种对象: 内置对象----js系统自带的对象 自定义对象---自己定义的构造函数创建的对象 浏览器对象---BOM的时候讲 内置对象: Math Date String Array Object //如何验证变量是不是对象? console.log(Array instanceof Object); var obj={}; console.log(obj instanceof Object); 原文地址:https://www.cnblogs.com/jane-panyiyun/p/

Js基础知识7-Es6新增对象Map和set数据结构

前言 JavaScript中对象的本质是键值对的集合,ES5中的数据结构,主要是用Array和Object,但是键只能是字符串.为了弥补这种缺憾,ES6带来了一种新的数据结构Map. Map也是键值对的集合,只是键不仅可以是字符串还可以是其他数据类型,比如:对象(是不是很神奇).请看下面例子..下面话不多说了,来一起看看详细的介绍吧. Map 对象 Map结构提供了“值—值”的对应,任何值(对象或者原始值) 都可以作为一个键或一个值,是一种更完善的Hash结构实现.如果你需要“键值对”的数据结构

js基础(原型)

  function fun(){ alert(this.name); }; function Person(name , age , gender){ this.name = name; this.age = age; this.gender = gender; //向对象中添加一个方法 this.sayName = fun; } //每次创建对象都会新建一个sayName方法,而且是不一样的,这样完全没有必要,可以所有的对象共享同一个方法 //将sayName方法定义在全局中,污染了全局的作

js基础内容 原型与实例

对于原型的理解:当我们创建一个函数的时候,每个函数会自动生成一个原型(prototype)属性:在函数中就只有这一个原型属性,而这个属性是一个指针,指向一个对象,称为原型对象,原型对象中含有一个constructor属性,通过这个属性又可指回函数 当我们向函数中添加属性时,实际上添加到了原型对象之中,当我们用new操作符创建新实例时,这个新实例是可以共享原型对象中的属性的 当我们创建新实例时,这个实例中存在prototype属性,类似于函数 这个属性也是一个指针,指向函数的原型对象,但实例与函数

JS基础---常见的Bom对象

BOM(Browser Object Mode)浏览器对象模型,是Javascript的重要组成部分.它提供了一系列对象用于与浏览器窗口进行交互,这些对象通常统称为BOM. 一张图了解一下先 1.window 对象--BOM核心 window,顾名思义,窗口对象.它表示整个浏览器窗口,主要用来操作浏览器窗口.同时, window对象还是 ECMAScript 中的 Global 对象,因而所有全局变量和函数都是它的属性,且所有原生的构造函数及其他函数也都存在于它的命名空间下. 弹框类的方法.前面

JS基础知识——原型与原型链

1.如何准确判断一个变量的数组类型 2.写一个原型链继承的例子 3.描述new一个对象的过程 4.zepto(或其他框架中如何使用原型链) 知识点: (1)构造函数 function Foo(name,age){ this.name = name this.age = age this.class = 'class-1' //return this //默认有这一行 } var f = new Foo('Jay',20);//可以创建多个对象 (2)构造函数——扩展 var a = {} 是 v

js基础,Array 数组对象、BOM 浏览器对象模型

Array 数组对象 定义数组的 3种方式 var week = new Array(); var week = new Array(‘星期一’ , ‘星期二, ‘星期三’); var week = (‘星期一’ , ‘星期二, ‘星期三’); 常用方法: 获取数组的长度 .length: alert(week.length); 获取数组下标所对应的值: alert(week[0]); 数组元素添加: 将一个或多个新元素添加到数组结尾,并返回数组新长度 var week_len = week.p

JS基础知识梳理---String对象

A:对象的声明 var stringObject = new String(“hello word”); var stringObjectB = “hello word”; B:StringObject具备的属性 StringObject.length,字符串长度(空格也占位);相应的,可以通过string[n]来访问字符串中角标为n的字符 var str = “today is good today”; console.log(str.length);//19 console.log(str[

【学习笔记】JS基于原型的面向对象

/*|------------------------------------------------------| *|--js是基于原型prototype而不是类class的面相对象语言----| *|--js只有对象和对象的实例,没有class-------------------| *|--Z_LY-2015-11-15-------------------------------------| *|--------------------------------------------