前端开发基础-JavaScript(二)(javascript前端开发教程)
wxin55 2025-05-09 22:14 2 浏览 0 评论
Object
JavaScript的所有对象都衍生于Object对象,所有对象都继承了Object.prototype上的方法和属性,虽然它们可能会被覆盖,熟悉它对于编程能起到很大的作用,也能比较深刻的了解JavaScript这门语言。
Object
创建一个对象可以使用new,也可以使用快速创建的方式:
var _object = {};
_object对象中就可以使用Object.prototype中所有的方法和属性,虽然看起来它是空的。说到这里在编程中常常有一个非常有用的需求,如何判断一个对象是空对象。
这是zepto中的判断一个对象是否是空对象,常常使用:
$.isEmptyObject = function(obj) { var name for (name in obj) return false
return true}
也顺便看了下jQuery原理是一模一样的:
isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false;
} return true;
}
使用in操作符来实现,它不会遍历到父原型链。
constructor返回一个指向创建了该对象的函数引用,这个东西主要是可以用来识别(类)到底是指向哪里的。
defineProperty直接在一个对象上定义一个新属性,非常适合用于动态构建,传入三个参数[动态添加对象的目标对象,需要定义或被修改的属性名,需要定义的对象],在第三个参数中可以有些属性来表示是否继承(proto),要不要定义get,set方法,enumerable是否可枚举。
defineProperties跟上述defineProperty一样,但是它可以添加多个。
getOwnPropertyNames返回一个由指定对象的所有属性组成的数组
keys返回一个数组包括对象所有的属性(可枚举)
keys是经常会用到的一个属性,它只能包可枚举的,如果想获取一个对象的所有属性包括不枚举的,那么使用getOwnPropertyNames。
hasOwnProperty用于判断某个对象是否包含有自身的属性,这个方法常常用于检测对象中的属性是否存在,它只检测自身,对于继承过来的都是false,这一点是非常重要的理解。
isPrototypeOf 用于检测一个对象是否在另一个对象的原型链上,比如有两个对象是互相交互的,常常会使用它来进行检测。
propertyIsEnumerable这个方法也比较重要,返回一个布尔值,检测一个对象的自身属性是否可以枚举
可枚举的理解,也就是对象的属性可枚举,它的属性值不可以修改,但是在Js中它有自己的定义,引擎内部看不见的该属性的[[Enumerable]]特性为true,那么就是可枚举的。基本上把一个普通对象可以看做是一个枚举类型,比如var color = {'red':1},red是可以修改的,但是red是可枚举的,但是如果是继承过来的属性,propertyIsEnumerable是返回false的,它还有一个特点,就是自身。
如果要定义不可枚举的属性,那就要使用defineProperty方法了,目前不能用对象直接量或者构造函数定义出来。
var obj = {name: 'jack', age:23}Object.defineProperty(obj, 'id', {value : '123', enumerable : false });
深拷贝与浅拷贝
关于拷贝的问题,主要分为深拷贝和浅拷贝,但是如果从空间分配上来说JavaScript的拷贝不应该算是深拷贝,比如:
var d = {};for(k in a){
d[k] = a[k];
}return d;
今天突然想到了这么一个问题,在C语言中,所谓的拷贝,就是分两种情况,一种是把指针地址拷贝给另外一个变量,虽然也开辟的了一个内存空间,在栈上也存在着一个地址,我对这个变量进行修改,同一个指针是会改变其值的,这种拷贝叫浅拷贝。另外一种情况,直接开辟一个新空间,把需要复制的值都复制在这个新的空间中,这种拷贝叫中深拷贝。
如果看到上述的一段Js代码,很多人说它是浅拷贝,假设传入一个a对象,拷贝完成之后返回一个d,当我修改返回对象的值时并不能同时修改a对象,于是,在这里我有一个很大的疑问,在Js中到底什么是浅拷贝,什么是深拷贝的问题?
这一点上感觉Js真的很奇葩,如果在开发iOS中,不可变对象copy一下,依然是不可变,所以是浅拷贝,拷贝了指针变量中存储的地址值。如果是可变对象copy一下,到不可变,空间变化了,包括不可变mutableCopy到不可变,空间依然变化了,所以是深拷贝。但是JavaScript中对于这一点要考虑一种情况,值类型,和引用类型,这个基础知识,我相信大家都非常清楚。数字,字符串等都是值类型,object,array等都是引用类型。
var a = [1,2,3];var b = a;b.push(4);console.log(a); //[1,2,3,4]var numb = 123;var _numb = numb;
_numb = 567;console.log(numb); //123
从这个例子中可以看的出来,它们使用的都是=符号,而数组a发生了变化,numb数字却没有发生变化。那么从这里,可以有一个总结,所谓了深拷贝,浅拷贝的问题,应该针对的是有多个嵌套发生的情况。不然假设是这样的情况,还能叫浅拷贝么?
var object = {"de":123};var o = copy(object);
o.de = 456;console.log(object) //{"de":123}
明显对象o中的de属性修改并没有影响到原始对象,一个对象中的属性是一个字符串,如果从内存空间的角度上来说,这里明显是开辟了新的空间,还能说是浅拷贝么?那么针对另外一种情况。
var object = { "de":{ "d":123
}
}var o = deepCopy(object);o.de.d = "asd";
如果一个对象中的第一层属性,不是值类型,只单层循环,这样来看的话确实是一个浅拷贝,因为在Js中引用类型用=赋值,实际上是引用,这样说的通。所以,深拷贝,还需要做一些处理,把object,array等引用类型识别出来,深层递归到最后一层,一个一个的拷贝。
var deepCopy = function(o){ var target = {}; if(typeof o !== 'object' && !Array.isArray(o)){ return o;
} for(var k in o){
target[k] = deepCopy(o[k]);
} return target;
}
思路是如此,这个例子只考虑了两种情况,对象和数组,为了验证这样的思路,最后的结果与预期是一样的。
var _copy = { 'object':{ 'name':'wen'
}, 'array':[1,2]
}var h = deepCopy(_copy);h.object.name = 'lcepy';h.array[1] = 8;console.log(h);console.log(_copy);
面向对象
面向对象的语言有一个非常明显的标志:类,通过类来创建任意多个具有相同属性和方法的对象,可惜的是Js里没有这样的概念。
但是Js有一个特性:一切皆是对象。
聪明的开发者通过这些特性进行摸索,于是迂回发明了一些程序设计,以便更好的组织代码结构。
工厂模式
主要是用来解决有多个相同属性和方法的对象的问题,可以用函数来封装特定的接口来实现
var computer = function(name,version){ return { 'name':name, 'version':version, 'showMessage':function(){ alert(this.name);
}
}
}var test = computer('apple','11.1');test.showMessage();
构造函数模式
我们知道像原生的构造函数,比如Object,Array等,它们是在运行时自动出现在执行环境中的。因此,为了模仿它,这里也可以通过一个普通的函数,并且new出一个对象,这样就成为了自定义的构造函数,也可以为他们添加自定义的属性和方法。
但是这样的构造函数有一个缺陷,就是每个方法都会在每个实例上创建一次,因为每次创建都需要分配内存空间,但是有时候这样的特性还是有用的,主要是要控制它们,在不使用的时候释放内存。
var Computer = function(name,version){ this.name = name; this.version = version; this.showMessage = function(){ alert(this.name);
}
}var apple = new Computer('apple',2014);var dell = new Computer('dell',2010);apple.showMessage();dell.showMessage();
像apple,dell是通过Computer实例化出来的不同的对象,但是它们的constructor都是指向Computer的。这里也可以使用instanceof来对(对象)进行检测。
在书写上构造函数跟其他函数是没有什么区别的,主要的区别还是在使用上,构造函数需要使用new操作符。
其实这样的书写,已经跟类没有什么区别了,表面上来看,而构造函数我个人更倾向于一个类的某个静态方法。
原型模式
说到原型模式就不得不提一提关于指针的问题,因为每一个函数都有一个prototype属性,而这个属性是一个指针,指向一个对象。
C语言描述指针,这个在iOS开发中非常重要
比如我先定义一个int类型的指针变量和一个普通的int类型数据,然后给指针变量赋值。
int *p; int pp = 123;
p = &pp;
*p = 999; printf('%d',pp);
*是一个特殊符号用于标明它是一个指针变量。
&是地址符
分析这个就要说到栈内存和堆内存了,比如*p在栈内存中分配了一个地址假设是ff22x0,它还没有空间。而pp存在一个地址ff23x0,并且分配了一个空间存储着123,这个地址是指向这个空间的。
p = &pp 这样的赋值操作,也就是把ff23x0取出来,并且给p分配一个空间把ff23x0存储进去,并且ff22x0指向这个空间。
*p = 999 从这里就可以看出来p操作的是地址,而这个地址不就是ff23x0么,于是pp成了999。
所谓的指针也就是存储着地址的变量。
回到原型上,如果每一个函数中的 prototype属性都是一个指针,实际上它只是一个地址引用着一个空间,而这个空间正是我们写的xxx.prototype.xxx = function(){}这样的代码在运行时分配的空间。那么可见,使用原型的好处是空间只分配一次,大家都是共享的,因为它是指针。
先看一个例子
var Computer = function(name){ this.name = name;
}Computer.prototype.showMessage = function(name){ alert(name);
}var apple = new Computer('apple');var dell = new Computer('dell');Computer.prototype.isPrototypeOf(apple);
在解释这个原型链之前,还要明白Js的一个特性,就是如果自身不存在,它会沿着原型往上查找。它的原理稍微有些绕,Computer自身的prototype是指向它自身的原型对象的,而每一个函数又有一个constructor指向它自身,prototype.constructor又指向它自身。于是Computer的两个实例apple,dell内部有一个proto属性是指向Computer.prototype的,最后的结果是它们可以使用showMessage方法。
当然它们还有一个搜索原则,比如在调用showMessage的时候,引擎先问apple自身有showMessage吗?“没有”,继续搜索,apple的原型有吗,“有”,调用。所以从这里可以看出,this.showMessage是会覆盖prototype.showMessage的。
另外还可以使用isPrototypeOf来检测一个对象是否在另一个对象的原型链上,上述的代码返回的是true。
apple.hasOwnProperty('name')apple.hasOwnProperty('showMessage')
使用hasOwnProperty来检测到底是对象属性还是原型属性,使用this创建的属性是一个对象属性。
从上面可以看出来原型链的好处,但是它也不是万能的,正因为指针的存在,对于某些引用类型来说这个就非常不好了,我需要保持原对象属性值是每一个对象特有的,而不是共享的,于是把之前的构造函数与原型组合起来,也就解决了这样的问题。
var Computer = function(name){ this.name = name;
}Computer.prototype.showMessage = function(){ alert(this.name);
}var apple = new Computer('apple');apple.showMessage();
这样的结果是在对象中都会创建一份属于自己的属性,而方法则是共享的。
动态原型模式
有时候遇到某些问题需要动态添加原型,但是实例中是不能添加的,所以绕来一下,在初始化构造函数中添加。
var Computer = function(){ if(typeof this.showMessage !== 'function'){ Computer.prototype.showMessage = function(){
}
}
}
只要初始化了一次,以后就不用修改了。
寄生构造函数模式
这种模式的原理就是在一个函数中封装需要创建对象的代码,然后返回它。
var test = function(name){ return { 'name':name
}
}var g = new test('apple');var f = de('dell');
看起来它跟工厂模式还是很像的,
稳妥模式
这种模式主要是在解决需要安全的环境中使用,一般来说一个类如果不提供getter,setter方法,是不允许直接访问和修改的。
var computer = function(name){ var _name = name; return { 'getter':function(){ return _name;
}, 'setter':function(name){
_name = name;
}
}
}
这样的方式可以保证属性或者说是数据的安全性,不允许直接随便修改,如果不提供setter方法的话,压根就不允许。
早读课提醒
言归正传我们在微信群中推出了《早读课》,每日分享一篇我们认真精选的文章(不限于前端开发类),其目的是帮助开发者来学习有价值的东西。想加微信群的朋友,直接添加我的微信号:icepy_1988,审核之后会邀请你入群。想加QQ群的朋友,可以直接添加:418898836,答对问题即可入群。
关注我们
更多精彩内容可关注微信公众号:搜索 fed-talk ,来关注我们吧,也欢迎你将它分享给自己的朋友。
相关推荐
- 武山县农业农村举办苹果枝枯病监测防控技术培训班
-
苹果枝枯病是苹果主要病害之一,主要危害苹果枝干,造成枯枝和枯干,影响苹果产量,该病的发生危害严重,蔓延迅速,直接影响苹果树势及产量,针对武山县实际情况,保障全县果业生产安全,近日,县农业农村局组织植保...
- 2017年基层农技推广体系改革与建设项目苹果科技示范基地举办苹果产业理论第二期培训班
-
2018年3月23日下午,富民树美果蔬产销专业合作社在百花山苹果科技示范基地基地,举办2017基层农技推广体系改革与建设项目苹果产业理论第二期培训班。参加培训人员全部来2017年基层体系建设富民树美果...
- 小苹果“国标班”即将开课!请大家关注乐动族看课程表
-
小苹果“国标班”即将开课!请大家关注乐动族看课程表时间:2015-04-0406:12:05来源:扬子晚报作者:责任编辑:郑泽川各位爱好舞蹈健身的朋友们,扬子晚报体育公众号“乐动族”发福利了!...
- 苹果:人人能编程(苹果人人能编程人人能创造)
-
版权声明本文首发于微信公共帐号:学习学习再学习(xiaolai-xuexi)请注意:无需授权即可转载;甚至无需保留以上版权声明……iPad上有个值得吐血推荐的应用,叫SwiftPlayg...
- “小苹果”培训班开始报名了(小苹果培训班怎么收费)
-
扬子晚报体育类微信订阅号“乐动族”,与“南京群颐文化信息咨询有限公司”和“南京悦美健身俱乐部”合作,开展“国标版”小苹果健身广场舞的教学、普及工作。普及班的开课时间和地点已经出炉(见表),通过“乐动...
- 镇原县农技中心举办苹果有机肥替代化肥项目技术培训班
-
4月19日,镇原县农技中心举办苹果有机肥替代化肥项目技术培训班。本次培训旨在进一步打造镇原优质生态绿色环保苹果品牌。平泉镇秦铺村果农秦浩鹏说:“通过培训我学到了很多技术经验,也认识到果园增施有机肥能提...
- 洛宁:苹果产业奏响“科技+传统”协奏曲 智慧果园谱写产业升级新篇章
-
四月的豫西大地春意盎然,河南洛宁县上戈镇的万亩苹果园迎来了一年中最富诗意的时节。远望如雪浪翻涌,近观似繁星缀枝,苹果花开的盛景不仅吸引着八方游客,更孕育着果农们全年的希望。在这片生机勃勃的土地上,一场...
- 苹果在意大利开办 iOS 应用开发课程,首批 600 名学生 10 月开课
-
如果你正计划学习编程,同时身处意大利的话,接下来的消息可能会对你有帮助。苹果与意大利那不勒斯腓特烈二世大学(UniversityofNapoliFedericoII)合作,开办了一个iOS...
- 合阳县举办苹果种植大户培训班(合水县苹果种植面积)
-
10月11日,合阳县农广校在甘井镇孟村举办了2018年新型职业农民苹果种植大户培训班,进一步提升了新型职业农民综合素质。根据实际情况,农广校制定了招生简章,严格按照个人申请、村委推荐、乡镇初审、县农广...
- 清水县组织举办2024年东西部科技协作苹果新品种引进项目技术培训班
-
9月21日,县科技局邀请天津农学院园艺学院教授梁兴,在金果果品种植农民专业合作社举办了2024年东西部科技协作苹果新品种引进项目技术培训班,合作社社员55人参加了培训。金果果品种植农民专业合作社今年争...
- TypeScript中的类型详解(typescript的特性)
-
2021年,TypeScript非常火热,前端的各大主流框架和工具,都在向TypeScript靠拢,TypeScript让前端开发复杂大型项目更加严谨。极大的降低了代码出现bug的几率,也大大增强了代...
- 前端开发基础-JavaScript(二)(javascript前端开发教程)
-
ObjectJavaScript的所有对象都衍生于Object对象,所有对象都继承了Object.prototype上的方法和属性,虽然它们可能会被覆盖,熟悉它对于编程能起到很大的作用,也能比较深刻的...
- JS不只是简单的构造模块(读书笔记)
-
一、人们常会遇到诸如对象、基本类型、字面值这样的术语,三者之间有何区别,如何分辨?JS字面值:表示某种特定类型的一个值,如一个字符串(String)、浮点数(Number)、布尔值(Boolean)...
- js基础学习(js基础总结)
-
vscode运行js要在VSCode中运行JavaScript代码,你需要按照以下步骤操作:首先确保你已经安装了Node.js。如果没有安装,可以从官网(https://nodejs.org/)下载并...
- Java和JavaScript之间的区别(java和javascript有啥区别)
-
Java和Javascript都最适合它们的使用,并且两者也有相对不同的地方。Java通常是:一种强大的计算机编程语言。它是构建软件应用程序的独立计算平台。它将每个项目视为对象和类。Java...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- hive行转列函数 (63)
- sourcemap文件是什么 (54)
- display none 隐藏后怎么显示 (56)
- 共享锁和排他锁的区别 (51)
- httpservletrequest 获取参数 (64)
- jstl包 (64)
- qsharedmemory (50)
- watch computed (53)
- java中switch (68)
- date.now (55)
- git-bash (56)
- 盒子垂直居中 (68)
- npm是什么命令 (62)
- python中+=代表什么 (70)
- fsimage (51)
- nginx break (61)
- mysql分区表的优缺点 (53)
- centos7切换到图形界面 (55)
- 前端深拷贝 (62)
- kmp模式匹配算法 (57)
- jsjson字符串转json对象 (53)
- jdbc connection (61)
- javascript字符串转换为数字 (54)
- mybatis 使用 (73)
- 安装mysql数据库 (55)