深入理解 Javascript 之 对象
撸js基础之对象
图例
先谈谈 ECMAScript 中的数据类型
ES6 之前 ECMAScript 中有 5 种简单数据类型(也称为【基本数据类型】):Undefined
、Null
、Boolean
、Number
和 String
。
还有一种复杂的【引用数据类型】Object
。
ES6
引入了一种新的原始数据类型 Symbol
,表示独一无二的值。它是 JavaScript 语言的第七种数据类型。它也是基本数据类型。
- 特点
基本数据类型的值是按值访问的 基本类型的值是不可变的 基本类型的比较是它们的值的比较 基本类型的变量是存放在栈内存(Stack)里的 引用类型的值是按引用访问的 引用类型的值是可变的 引用类型的比较是引用的比较 引用类型的值是保存在堆内存(Heap)中的对象(Object) 与其他编程语言不同,JavaScript 不能直接操作对象的内存空间(堆内存)
图解:
检测变量类型
typeof
适合判断基本数据类型和function的判断
typeof "sss" ===> "string" typeof 123 ===> "Number" typeof [1,2,3] ===> "object" typeof new Date() ===> "object" typeof function(){alert('111');} ===> "function" typeof undefined ===> "undefined" typeof NaN ===> "number" typeof null ===> "object"
instanceof
判断已知的对象类型或者是自定义的对象
- 目标对象 + instanceof + 函数构造器[可以理解为是某个对象是否是某个构造器的实例]
- 原理: 判断左边的对象的原型链上是否有右侧的构造函数的prototype属性
[1,3] instanceof Array === true new Array('1, 3,4') instanceof Array === true new Object() instanceof Object === true new String("string") instanceof String === true function(){this.name="22";} instanceof Function === true // 定义一个构造函数 function Person(){ } // 定义一个构造函数 function Student(){ } // 每一个构造函数都有一个prototype对象属性, 这个对象属性将会作为通过new Person()创建的对象的一个原型。 // 也就是当我们在new 一个对象的时候,这个对象的原型就指向了这个构造函数的prototype。 Student.prototype = new Person(); // student继承至person var bson = new Student(); bson instanceof Student // false bson instanceof Person // true
Object.prototype.toString.apply()
判断基本数据类型和内置对象
Object.prototype.toString.apply([]) === "[object Array]" Object.prototype.toString.apply(function(){}) === "[object Function]" Object.prototype.toString.apply(new Function); // "[object Function]" Object.prototype.toString.apply(new Object); // "[object Object]" Object.prototype.toString.apply(new Date); // "[object Date]" Object.prototype.toString.apply(new Array); // "[object Array]" Object.prototype.toString.apply(new RegExp); // "[object RegExp]" Object.prototype.toString.apply(new ArrayBuffer); // "[object ArrayBuffer]" Object.prototype.toString.apply(Math); // "[object Math]" Object.prototype.toString.apply(JSON); // "[object JSON]" var promise = new Promise(function(resolve, reject) { resolve(); }); Object.prototype.toString.apply(promise); // "[object Promise]" Object.prototype.toString.apply(124) // "[object Number]" Object.prototype.toString.apply("222") // "[object String]" Object.prototype.toString.apply(true) // "[object Boolean]" Object.prototype.toString.apply(null) // "[object Null]" Object.prototype.toString.apply(null) === "[object Null]" // 在IE6/7/8下存在有兼容性问题
创建对象
使用 Object 构造函数创建
// 对象实例的创建 var obj = new Object() obj.key = 'value' //使用构造函数创建一个空对象,并赋值
使用对象字面量表示法创建
//使用字面量创建一个对象 var obj = { key1: 'value1', key2: 'value2' }
ES6中还有更简洁的
var age = 20 var sex = "sexy" var a = { name: 'jack', // 简洁表示法,等同于 age: age age, // 简洁表示法,等同于 sayName: function() {} sayName(){}, // 属性名表达式,等同于 lover: 'rose' ['lo' + 'ver']: 'rose', // 属性名表达式,等同于 sexy: 'male' [sex]: 'male' }
工厂模式[创建多个相似的对象]
var createPerson (name, age){ var o = {}; o.name = name; o.age = age; o.sayName = function(){ console.log(this); } return o; } var a = createPerson ('zjj', 20); var b = createPerson ('zmf', 30);
工厂模式虽然解决多创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。
模仿“类”的设计
构造函数模式
function Person (name, age) { this.name = name; thia.age = age; this.sayName = function() { alert(this.age) } } Person.prototype.count = 2; var a = new Person('a', 20) var b = new Person('b', 22) a instanceof Person // true
- 构造函数与其他函数唯一的区别就在于调用他们的方式不同。任何函数只要通过new 操作符来调用,那它就可以作为构造函数。
使用new操作符调用函数
function CO(){ this.p = “I’m in constructed object”; this.alertP = function(){ alert(this.p); } } var o2 = new CO(); var obj = {}; // 第一步创建一个空对象 obj.__proto__ = CO.prototype; // 该对象的原型链指向构造函数的 prototype 所指向的对象。 CO.call(obj); // 第三步,将构造函数的作用域赋值给新的对象 return obj; // 返回新的对象
自定义一个new()
function Person(name, age) { this.name = name; this.age = age; } function New(f) { return function() { var o = {"__proto__": f.prototype} f.apply(o, arguments); return o; } }
上面这种构造函数解决了对象类型识别的问题,但是每个方法都要在每个实例上重新创建一遍,在上面的例子中,a 和 b 都有个名为sayName()的方法,这两个方法虽然名字、内容、功能相同,但却分别在 a 和 b 中都重新创建了一次,这是没有必要的。
更好的方法应该是将公用的方法放到他们的原型上,也就是接下来要说的原型模式。
原型模式
所有函数都有一个不可枚举的 prototype(原型)属性,这个属性是一个指针,指向一个对象。
Person.prototype
返回如下:
仔细分析下面的图,将会加深你的理解
prototype 和 proto
我们有一个person类
function Person (name, age) { this.name = name; thia.age = age; this.sayName = function() { alert(this.age) } } Person.prototype.count = 2; var p = new Person('zjj', 10);
对象p有一个__proto__属性,其指向构造器的原型
p.__proto__ == Person.prototype
foo 是一个类(构造器) fooObj是new foo() 之后产生的。 fooObj的 __proto__ 指向构造器原型(foo.prototype) foo 通过prototype 指向 构造器原型(foo.prototype) 构造器原型(foo.prototype)的构造器属性constructor 指向 foo
Person.__proto__ === Function.prototype
__proto__究竟指向谁
原型链
由于Person.prototype.__proto__ === Object.prototype,这就
相信看了上面两幅图,大家一定对原型链有了更深的理解和认识了吧!!
相关推荐
nmgxzm00 2020-11-10
ifconfig 2020-10-14
hhanbj 2020-11-17
zfszhangyuan 2020-11-16
古叶峰 2020-11-16
一个智障 2020-11-15
jipengx 2020-11-12
81427005 2020-11-11
xixixi 2020-11-11
游走的豚鼠君 2020-11-10
苗疆三刀的随手记 2020-11-10
Web卓不凡 2020-11-03
小飞侠V 2020-11-02
帕尼尼 2020-10-30
爱读书的旅行者 2020-10-26
帕尼尼 2020-10-23
杏仁技术站 2020-10-23
淼寒儿 2020-10-22