JavaScript对象、函数(你不知道的JavaScript)

一、对象

var obj = {};
obj[true] = "foo";
obj[3] = "bar";
obj[obj] = "baz";

obj["true"];
obj["3"];
obj["[object Object]"];

二、数组也是对象

var ary = ["foo", 42, "bar"];
ary.baz = "baz";
ary.length;	//3
ary.baz;

/* 如果试图想数组添加一个属性,但是属性名“看起来”像一个数字,那么它会变成一个数值下标 */
ary["4"] = "baz";
ary.length;	//5
ary[4];

三、对象属性

writable:可写(修改)

enumerable:可枚举(for ... in)

configurable:可配置(配置、删除)

注意:delete只能删除对象(可删除)属性,即configurable为true的属性。

var obj = {};
Object.defineProperty(obj, "a", {enumerable:true, value:2});
Object.defineProperty(obj, "b", {enumerable:false, value:3});

/* 检查给定属性名是否直接存在于对象中(而不是在原型链上)并满足enumerable:true */
obj.propertyIsEnumerable("a");	//true
obj.propertyIsEnumerable("b");	//false

/* 返回一个数组,包含所有(自身)可枚举属性 */
Object.keys(obj);	//["a"]
/* 返回一个数组,包含所有(自身)属性 */
Object.getOwnPropertyNames(obj);	//["a", "b"]

注意:in和hasOwnProperty(..)的区别在于是否查找[[Prototype]]链,然而,Object.keys(..)和Object.getOwnPropertyNames(..)都只会查找对象直接包含的属性。

四、对象原型

获取对象原型:Object.getPropertyOf(..)

function Foo(){}
var foo = new Foo();
Foo.prototype === Object.getPrototypeOf(foo);	//true

注意:在面向类的语言中,类可以复制(实例化)多次,就像用模具制作东西一样。在JavaScript中,并没有类似的复制机制。不能创建一个类的多个实例,只能创建多个对象,它们[[property]]关联的是同一个对象。这样就可用通过委托访问对象的属性和方法了。

类理论:在构造完成后,通常只需要操作这些实例(而不是类),因为每个实例都有你需要完成任务的所有行为。

五、原型链[[prototype]]

[[prototype]]机制就是存在于对象中的一个内部链接,它会引用其他对象。

var foo = {
	something:function(){
		// ....
	}
};
var bar = Object.create(foo);	// 创建新对象bar,并将其关联到对象foo上。

Object.create(null)会创建一个拥有空链接的对象,这个对象无法进行委托,其不存在原型链,所以instanceof总是返回false。其不受原型链干扰,非常适合用来存储数据!

对象之间的关系不是复制而是委托!!!

谈及原型链不得不提及我们经常在JavaScript中的类型检查!即内省:检查实例的类型;主要目的是通过创建方式来判断对象的结构和功能。

方式一:a instanceof Foo

方式二:“鸭子类型”:如果看起来像鸭子,叫起来像鸭子,那就一定是鸭子。

if(a.something) {
	a.something();	// something()并不一定在a自身上
}

方式三:isPrototypeOf()、getPrototypeOf()

建议使用方式三!!!

六、函数

JavaScript中的函数无法(用标准、可靠的方法)真正地复制,所以只能共享函数对象的引用。这意味着,如果修改共享函数,比如增加一个属性,所有引用地方都会随之修改!

七、构造函数

function Foo(){}
Foo.prototype = {};

var a1 = new Foo();
a1.constructor === Foo;		//false
a1.constructor === Object;	//true

详解:

创建一个新对象并替换了函数默认的.prototype对象引用,那么新对象并不会自动获得.constructor属性。

a1并没有.constructor属性,所以它会委托[[Prototype]]链上的Foo.prototype。但是这个对象也没有.constructor属性,所以它会继续委托给链顶端的Object.protoype。

实际上,对象的.constructor会默认指向一个函数,这个函数可以通过对象的.prototype引用!

总之,constructor并不表示被构造!!!改变prototype并不能彻底改变继承关系!!!

function Foo(name){
	this.name = "FenFei"
}
function Bar(){}

错误理解一:

Bar.prototype = Foo.prototype;
Bar.prototype.myTest = 123;
new Foo().myTest;	//123

并不会创建一个关联到Bar.prototype的新对象,它只是让Bar.prototype直接引用Foo.prototype对象。当执行类似Bar.prototype.myTest = 123的赋值语句时会直接修改Foo.prototype对象本身。

错误理解二:

Bar.prototype = new Foo();
new Bar("Camile").name;	//FenFei

的确会创建一个关联到Bar.prototype的新对象。但是它使用了Foo()的“构造函数调用”,如果Foo有副作用(比如注册到其他对象、给this添加数据属性等等),就会影响Bar()的后代。

正确处理方式一[ES6之前]:

Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.myTest = 123;
new Foo().myTest;	//undefined
new Bar("Camile").name;	//undefined

正确处理方式二[ES6之后]:

Object.setPrototypeOf(Bar.prototype, Foo.prototype);
Bar.prototype.myTest = 123;
new Foo().myTest;	//undefined
new Bar("Camile").name;	//undefined

八、函数关系

(1)在a的整条[[prototype]]链中是否有指向Foo.prototype的对象?

a instanceof Foo;

(2)在a的整条[[prototype]]链中是否出现过Foo.prototype?

Foo.prototype.isPrototypeOf(a);	// 不需要间接引用函数Foo,它的prototype属性会自动访问。

(3)区别

isPrototypeOf()方法可以判断对象间的关系。

b是否出现在c的[[prototype]]链中?

b.isPrototypeOf(c);

示例:

function Foo(){}
var a = new Foo();
console.log(a instanceof Foo);		// true
console.log(Foo.prototype.isPrototypeOf(a));	// true
var b = {};
var c = Object.create(b);
console.log(b.isPrototypeOf(c));	// true
console.log(b instanceof c);		// TypeError

在传统面向类的语言中,类定义之后就不会进行修改,所以类的设计模式不支持修改。但是JavaScript最强大的特性之一就是它的动态性,任何对象的定义都可以修改(除非你把它设置成不可变)!

[转载请标明出处:http://blog.csdn.net/ligang2585116]

版权声明:本文为博主原创文章,未经博主允许不得转载。转载请标明出处:http://blog.csdn.net/ligang2585116!

时间: 2024-08-24 18:59:43

JavaScript对象、函数(你不知道的JavaScript)的相关文章

JavaScript提升(你不知道的JavaScript)

最近,在读<你不知道的JavaScript(上卷)>这本书,书中详细阐述了JavaScript众多重要但经常被大家忽略的点,在此强烈推荐!!!书中,第4章讲述了"提升",从示例出发讲述了变量和函数提升的过程,纠正了自己以前错误的理解(相信好多人理解都是错误)! 我们习惯将var a = 2;看做一个声明,而实际上JavaScript引擎不这么认为!下面几个示例让你彻底搞懂JavaScript中的变量提升! 示例1: a = 2; var a ; console.log(a)

javascript 对象的扩展性

javascript 对象 的可扩展性 javascript 对象中的可扩展性指的是:是否可以给对象添加新属性.所有的内置对象和自定义对象显示的都是可扩展的,对于宿主对象,则有javascript 引擎决定. 下面有几个函数是设置对象的可扩展性: 1.Object.isExtensible(Object); 检查对象是否可以扩展. 2.Object.preventExtensions(Object) 设置对象不可扩展,也就是不能添加新的属性,但如果该对象的原型,添加了新的属性,那么该对象也将继承

JavaScript对象分类

JavaScript 中的对象分类 我们可以把对象分成几类. 宿主对象(host Objects):由 JavaScript 宿主环境提供的对象,它们的行为完全由宿主环境决定. 内置对象(Built-in Objects):由 JavaScript 语言提供的对象. 固有对象(Intrinsic Objects ):由标准规定,随着 JavaScript 运行时创建而自动创建的对象实例. 原生对象(Native Objects):可以由用户通过 Array.RegExp 等内置构造器或者特殊语法

JavaScript中两种类型的全局对象/函数

这里所说的JavaScript指浏览器环境中的包括宿主环境在内的. 第一种是ECMAScript Global Object,第二种是宿主环境(Host)下的全局对象/函数. 一.核心JavaScript内置对象,即ECMAScript实现提供的不依赖于宿主环境的对象 这些对象在程序执行之前就已经(实例化)存在了.ECMAScript称为The Global Object,分为以下几种 1, 值属性的全局对象(Value Properties of the Global Object).有NaN

Javascript使用函数apply扩展环境对象

Javascript使用函数apply扩展环境对象 通过实例对象作为参数传入调用构造函数对象的apply方法,以使实例对象作为环境对象在作为一个普通函数的构造函数中执行,构造函数的属性会覆盖到实例对象上,从而实现实例对象的属性扩展. 1.函数对象的apply和call传入参数     var tag = "global";      function say(){          for(var args = "", i = 0; i < arguments

JavaScript中函数对象的call()和apply()方法的总结

在JavaScript中,每个函数都有call()和apply()方法,用法举例如下: 先定义一个some_obj的对象,该对象有一个say()方法: var some_obj={ name:'Ninja', say:function(who){ return 'Haya ' + who + ', I am a '+ this.name; } }; 调用some_obj.say('Dude'); 输出:"Haya Dude, I am a Ninja" 再创建一个对象 var my_o

JavaScript 没有函数重载&amp;Arguments对象

对于学过Java的人来说,函数重载并不是一个陌生的概念,但是javaScript中有函数重载么...接下来我们就进行测试 <script type="text/javascript"> //JavaScript不存在函数重载现象 var add=function(a,b){ return a+b; } var add=function(a,b,c){ return a+b+c; } <span style="white-space:pre">

JavaScript中两种类型的全局对象/函数(转)

转自:http://www.cnblogs.com/snandy/archive/2011/03/19/1988626.html 这里所说的JavaScript指浏览器环境中的包括宿主环境在内的.第一种是ECMAScript Global Object,第二种是宿主环境(Host)下的全局对象/函数. 一.核心JavaScript内置对象,即ECMAScript实现提供的不依赖于宿主环境的对象 这些对象在程序执行之前就已经(实例化)存在了.ECMAScript称为The Global Objec

JavaScript 没有函数重载&amp;amp;Arguments对象

对于学过Java的人来说.函数重载并非一个陌生的概念,可是javaScript中有函数重载么...接下来我们就进行測试 <script type="text/javascript"> //JavaScript不存在函数重载现象 var add=function(a,b){ return a+b; } var add=function(a,b,c){ return a+b+c; } <span style="white-space:pre">

第三节(JavaScript 对象、函数)

JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等 在 JavaScript 中,对象是拥有属性和方法的数据 属性和方法 (属性是与对象相关的值.方法是能够在对象上执行的动作) 例: 学生 student student属性: student.name = 美女; student.age = 18 ; student.sex = 女 ; student.isMarry = true ; student的方法: student.eat() // 吃饭 student.slee