javascript语言精粹。3、对象;4、函数;深入原型链,对象的原理!
javascript的简单类型包括数字、字符、布尔值、null值和undefined值。
其他的类型都是对象。
对象是可变的键控集合。在javascript中,数组是对象,函数是对象,正则表达式是对象,对象自然也是对象。
对象是属性的容器,其中每个属性都拥有名字和值。
属性的名字可以是包括空字符串的任何字符串。属性的值可以是除了undefined之外的任意值
javascript的对象是无类别。它对新属性的名字和值没有约束。对象适合用于收集和管理数据。对象可以包含其他对象,
所以它们可以容易地表示成树形或者图形结构。
javascript包括一个原型链特性,允许对象继承另一对象的属性。
对象字面量
对象字面量提供了一种非常方便地创建新对象值的表示法。
var empty_object={};
原型
每个对象都连接到一个原型对象,并且它可以从中继承属性。
所有通过对象字面量创建的对象都连接到Object.prototype这个javascript种标准的对象。
枚举
for in 语句可用来遍历一个对象中的所有属性名。该枚举过程会列出所有的属性(包括原型中的属性)
一般使用hasOwnProperty方法和typeof来过滤
函数对象
在javascript中函数就是对象。对象是“名/值”对的集合并拥有一个连到原型对象的隐藏链接.
对象字面量产生的对象链接到 Object.prototype。 函数对象连接到 Function.prototype(该
原型对象本身连接到 Object.prototype).
每个函数在创建时有两个附加的隐藏属性: 函数的上下文和实现函数行为的代码.
每个函数对象在创建时也随带一个prototype属性。
它的值(函数对象的实例)是一个拥有constructor属性并且值即为该函数的对象。
调用
调用一个函数将暂停执行当前的函数。每个函数接收两个附加的参数:this和arguments。
this在面向对象编程中非常重要, 它的值取决于调用的模式(方法调用模式、函数调用模式、构造器调用模式、
apply调用模式)
方法调用模式 : 当一个函数保存为对象的一个属性时。我们称它为一个方法。this对象即为该对象
函数调用模式 : 当一个函数并非一个对象的属性时,那么它被当做一个函数来调用
构造器调用模式:如果在一个函数前面带上new来调用,那么将创建一个隐藏链接到该函数的 prototype 成员的新对象
,同时 this 将被绑定到那个新对象上
Apply调用模式
返回
一个函数总是会返回一个值。如果没有使用return指定返回,则返回undefined。
使用return语句,则return语句之后的代码不执行。
深入了解原型链、类型等
源码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" >
<head><title></title><script type="text/javascript">
window.onload = function() {
var div_show = document.getElementById("div_show");Object.prototype.objprototype = function() { }
Function.prototype.fnprototype = function() { }
Function.fnStaticfunction = function() { }
function people() {
this.sex = 0;
this.age = 1;
this.getName = function() { }}people.eat = function() { };
var p = new people();for (var i in people.prototype) {div_show.innerHTML += "peopleprototype: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in p) {div_show.innerHTML += "peopleinstance: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in people) {div_show.innerHTML += "people: " + i + "<br>";}div_show.innerHTML += "<br>";
function asia() { }
asia.StaticeatEastFood = function() { }
asia.prototype = new people();
asia.prototype.eatEastFoodPrototype = function() { }
var asian = new asia();for (var i in asian) {div_show.innerHTML += "asian: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in asia) {div_show.innerHTML += "asia: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in asia.prototype) {div_show.innerHTML += "asia: " + i + "<br>";}var stooge = {
"first-name": "J","last-name": "H",getName: function() { }
}div_show.innerHTML += "<br>";
for (var i in stooge) {div_show.innerHTML += "stooge: " + i + "<br>";}Function.prototype.method = function(name, value) {
this.prototype[name] = value;
}Number.method("getss", function() { });}</script></head><body><div id="div_show"></div>
</body></html>
. Object.prototype.objprototype = function() { }
Function.prototype.fnprototype = function() { }
Function.fnStaticfunction = function() { }
. function people() {
this.sex = 0;
this.age = 1;
this.getName = function() { }}//申明一个函数对象, 给该对象添加一个静态方法eat, 使用构造器调用函数生成实例p
people.eat = function() { };
var p = new people();
. for (var i in people.prototype) {div_show.innerHTML += "peopleprototype: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in p) {div_show.innerHTML += "peopleinstance: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in people) {div_show.innerHTML += "people: " + i + "<br>";}div_show.innerHTML += "<br>";
分析:
输出people.prototype里面的对象:
people.prototype对象为一个空的json对象,而所有的对象都会从原型链集成object.prototype的属性;因此第一个循环输出objprototypep是函数对象people的实例,因此它拥有people.prototype的所有属性以及各个私有属性。因此输出objprototypesexagegetName先从祖先输出。 (为什么可以输出fnprototype呢, 因为在这里使用 people instanceof Function得到true,我这么理解的:p是people的实例,因此能够得到people.prototype内的属性;而people是function的实例,因此只有people才能得到Function.prototype的属性)直接输出people内的对象(理解为作为Function实例输出Function.prototype属性;作为people类型,输出该“类”的静态方法)fnprototypeobjprototypeeat
//创建一个asia函数类, 添加一个静态方法StaticeatEastFood.
//使asia类继承自people类, 添加一个prototype方法, 实例化一个asian实例
function asia() { }
asia.StaticeatEastFood = function() { }
asia.prototype = new people();
asia.prototype.eatEastFoodPrototype = function() { }
var asian = new asia();. for (var i in asian) {div_show.innerHTML += "asian: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in asia) {div_show.innerHTML += "asia: " + i + "<br>";}div_show.innerHTML += "<br>";
for (var i in asia.prototype) {div_show.innerHTML += "asia: " + i + "<br>";}分析:
输出asian(asia实例)asian: eatEastFoodPrototype //asia的prototype拥有的
asian: getName //这三个是集成自people的
asian: ageasian: sexasian: objprototype //祖先object的
输出asiaasia: fnprototypeasia: objprototypeasia: StaticeatEastFood //静态方法
输出asia.prototypeasia: objprototype //祖先
asia: sex //继承自people的私有属性
asia: ageasia: getNameasia: eatEastFoodPrototype //自己的公共属性
. var stooge = {
"first-name": "J","last-name": "H",getName: function() { }
}div_show.innerHTML += "<br>";
for (var i in stooge) {div_show.innerHTML += "stooge: " + i + "<br>";}/*
stooge: objprototype
stooge: first-name
stooge: last-name
stooge: getName
*/
. Function.prototype.method = function(name, value) {
this.prototype[name] = value;
}/*
这是一个简单的扩展类型的方法的函数.
比如 people.method ('run',function(){alert('人类会跑');})
这是很简单没有问题的。
可是, Function.method , Number.method , String.method , 甚至Object.method这样也能访问
这个方法为自身扩展,为什么呢?
这是因为,所有的类型其实都是Object类型的实例。Object除了prototype外还有一个很重要的属性——
constructor。这个东西就是用来完成我前面说到的对object的扩充用的,它也是我们使用JavaScript模拟
OOP的基础。由于JavaScript中所有东西都是Object,所以constructor也是,不过它的原始类型是
Function(运行Object.constructor.valueOf()得到:function Function() { [native code] })。
这么说吧。既然Number、String等既然都是类型,那么他们的实例就需要类似一个new Number()这样的过程。
那么OK,Number其实他们都是一个函数对象而已。
(Number.constructor , 得到function()).
因此,他们包括object都是function类型的,Function.prototype的属性他们都有!!!
而所有对象都是object,function也是object,和其他类型一样,
因此Function.constructor为Function,Function instanceof Object :true
神奇吧~?!
*/
Number.method("getss", function() { });