JavaScript的js闭包对象和原型特性 如何给循环中的对象

发布于 06/04 20:16
在写商城的时候,想给通过for循环打印出的商品上,每个小栏目都添加一个删除按钮。但是该如何让js响应删除,并获取到该元素的值呢?换句话说,就是有不定个的按钮,且点击按钮时都需要执行一个方法(参数不一样)。
我想到的解决办法是,动态生成id,js中使用for循环统一解析。
js中的for循环,需要一个vos的size值,也就是商品的总数。问题是,在我的html中可以获取到vossize的值,但是js中就是获取不到。
之后考虑到时js和html的加载顺序问题,所以把js引入都放入了body的最后,问题结局。
问题3:(闭包)
之后又产生了一个问题,js中for循环的每一个function都只能读取到最后一个元素的值,为什么?
网上找到了这样的回答:
原因:(闭包)
因为在for循环里面指定给list_obj[i].onclick的事件处理程序,也就是onclick那个匿名函数是在for循环执行完成后(用户单击链接时)才被调用的。而调用时,需要对变量i求值,解析程序首先会在事件处理程序内部查找,但i没有定义。然后,又到方法外部去查找,此时有定义,但i的值是4(只有i大于4才会停止执行for循环)。因此,就会取得该值——这正是闭包(匿名函数)要使用其外部作用域中变量的结果。而且,这也是由于匿名函数本身无法传递参数(故而无法维护自己的作用域)造成的。
既然已经知道函数调用外部变量的时候就构成了一个闭包,里面的变量会受到别的地方的影响,那么我们
现在要做的就是,构建一个只有自己本身才可访问的闭包,保存只供本身使用的变量。
用一层i的新的function包围:
var list_obj = document.getElementsByTagName('li');
for (var i = 0; i &= list_obj. i++) {
(function(i){
//var p = i
list_obj[i].onclick = function() {
我的代码:
for(var i=1;i&=$("#vossize").val();i++){
var a="_"+i;
(function (a) {
$(document).ready(function(){
$("#btn_addtocart"+a).click(function(){
var dataJson = {
goodsid:$("#add_goodsid"+a).val()
url:"/addToCart",
type:"post",
data:dataJson,
contentType:"application/x-www-form-urlencoded",//默认为此,设置发送给后端的类型
dataType:"json",//设置接收后端的数据的类型
async:true,//设置异步,不然可能接收不到后端返回的json
success:function(data){
if(data.code==0){
//window.location="/cart/";
alert(data.msg);
window.location.reload();
fail:function () {
alert("ssss");
& 著作权归作者所有
人打赏支持
码字总数 62406
以下问题都来自于互联网前端面经分享,回答为笔者通过查阅资料加上自身理解总结,不保证解答的准确性,有兴趣讨论的同学可以留言或者私信讨论。 1.JS的异步机制? 2.闭包如何实现? 3.原型链、...
大雄的学习人生
先抛出原问题: for (var i = 0; i & 10; i++) {divs[i].onmouseover = function () { this.style.backgroundColor = "red"; this.style.left = -55i; };} 测试结果显示:鼠标经过所有div时......
第一部分:初遇闭包 http://www.runoob.com/js/js-function-closures.html 什么是闭包?闭包有什么作用?这是我遇到闭包时的第一反应。 闭包在JavaScript高级程序设计(第3版)中是这样描述:...
IT智云编程
前端开发最容易犯的13个JavaScript错误,你中标了没 开发者最容易犯的JavaScript错误,总结出13个。这些当中可能少不了你犯的错误^_^。我们描述了这些陋习,并列出来解决办法,希望对开发者有...
【前端工程师手册】JavaScript作用域拾遗 昨天总结了一些作用域的知识【前端工程师手册】JavaScript之作用域,但是发表完发现忘记了一些东西,今天拾个遗。 昨天说到了JavaScript中没有块级作...
推荐码发放
没有更多内容
加载失败,请刷新页面
性别歧视在日本:“我是女生,所以社会不让我学医” 毛西
1.今日导读 大家在看病的时候,有留意过女医生的比例吗?在性别歧视现象十分严重的日本,男医生和女医生的比例达到了惊人...
解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...
魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...
MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....
微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...
自由的开源
没有更多内容
加载失败,请刷新页面
文章删除后无法恢复,确定取消删除此文章吗?
亲,自荐的博客将通过私信方式通知管理员,优秀的博客文章审核通过后将在博客推荐列表中显示
确定推荐此文章吗?
确定推荐此博主吗?
聚合全网技术文章,根据你的阅读喜好进行个性推荐
指定官方社区
深圳市奥思网络科技有限公司版权所有理解javascript中的闭包
&更新时间:日 10:16:34 & 作者:咸鱼老弟
本文主要介绍了javascript中闭包的特性、作用、示例代码以及注意事项。具有一定的参考价值,下面跟着小编一起来看下吧
什么是闭包?
闭包的特性
闭包的作用:
闭包的代码示例
闭包在javascript来说是比较重要的概念,平时工作中也是用的比较多的一项技术。下来对其进行一个小小的总结
什么是闭包?
官方说法:
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量------《javascript高级程序设计第三版》
下面就是一个简单的闭包:
function A(){
var text="hello world";
function B(){
console.log(text);
var c=A();
c(); // hello world 
按照字面量的意思是:函数B有权访问函数A作用域中的变量(text),通过另一个函数C来访问这个函数的局部变量text。因此函数B形成了一个闭包。也可以说C是一个闭包,因为C执行的实际是函数B。
这个需要注意的是,直接执行A();是没有任何反应的。因为return B没有执行,除非是return B();
闭包的特性
闭包有三个特性:
&1.函数嵌套函数
&2.函数内部可以引用外部的参数和变量
&3.参数和变量不会被垃圾回收机制回收
解释一下第3点,为什么闭包的参数和变量不会被垃圾回收机制回收呢?
首先我们先了解一下javascript的垃圾回收原理:
(1)、在javascript中,如果一个对象不再被引用,那么这个对象就会被GC(garbage collection)回收;
(2)、如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。
上面的示例代码中A是B的父函数,而B被赋给了一个全局变量C(全局变量的生命周期直至浏览器卸载页面才会结束),这导致B始终在内存中,而B的存在依赖于A,因此A也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
闭包的作用:
其实闭包的作用也是有闭包的特性决定的,根据上面的闭包特性,闭包的作用如下:
& 1、可以读取函数内部的变量,而不是定义一起全局变量,避免污染环境
& 2、让这些变量的值始终保持在内存中。
闭包的代码示例
下面主要介绍几种常见的闭包,并进行解析:
demo1 局部变量的累加。
function countFn(){
var count=1;
return function(){
//函数嵌套函数
console.log(count);
var y = countFn(); //外部函数赋给变量y;
y(); //2 //y函数调用一次,结果为2,相当于countFn()()
y(); //3 //y函数调用第二次,结果为3,因为上一次调用的count还保存在内存中,没有被销毁,所以实现了累加
y= //垃圾回收,释放内存
y(); // y is not a function
由于第一次执行完,变量count还保存在内存中,所以不会被回收,以致于第二次执行的时候可以对上次的值就行累加。当引入y=null时,销毁引用,释放内存
demo2 循环中使用闭包
代码如下(下面的三个代码示例):我们的目的是想在每次循环中调用循环序号:
for (var i = 0; i & 10; i++) {
var a = function(){
console.log(i)
a() //依次为0--9
这个例子的结果是没有题的,我们依次打印出了0-9
每一层匿名函数和变量i都组成了一个闭包,但是这样在循环中并没有问题,因为函数在循环体中立即被执行了
但是在setTimeout中就不一样了
for(var i = 0; i & 10; i++) {
setTimeout(function() {
console.log(i); //10次10
我们期望的依次是打印出0--10,实际情况是打印出 10次10。即使吧setTimeout的时间改为0,也是打印出10个10。这是为什么呢?
这是因为setTimeout的一种机制,setTimeout是从任务队列结束的时候开始计时的,如果前面有进程没有结束,那么它就等到它结束再开始计时。在这里,任务队列就是它自己所在的循环。
循环结束setTimeout才开始计时,所以无论如何,setTimeout里面的i都是最后一次循环的 i。该代码中,最后的 i 为10,所以打印出了10个10.
这也就是为什么setTimeout的回调不是每次取循环时的值,而取最后一次的值
解决上面的setTimeout不能依次打印出循环的问题
for(var i=0;i&10;i++){
var a=function(e){
return function(){
console.log(e); //依次输入0--9
setTimeout(a(i),0);
因为setTimeout第一个参数需要一个函数,所以返回一个函数给它,返回的同时把 i 作为参数传进去,通过形参 e 缓存了i,也就是说e变量相当于是 i 的一个拷贝 ,并带进返回的函数里面。
当 setTimeout 的执行时,它就拥有了对 e 的引用,而这个值是不会被循环改变的。
也可以用下面的写法,和上面类似:
for(var i = 0; i & 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e); //依次打印出0-9
demo3 循环中添加事件
看下面的一个典型的demo.
我们希望每次点击li的时候,alert出li的索引值,所以用下面的代码:
&ul id="test"&
&li&第一个&/li&
&li&第二个&/li&
&li&第三个&/li&
&li&第四个&/li&
var nodes = document.getElementsByTagName("li");
for(i = 0,len=nodes.i&i++){
nodes[i].onclick = function(){
alert(i); //值全是4
事与愿违,无论点击哪一个li,都是alert(4),也就是都是alert循环结束之后的索引值。这是为什么呢?
这是因为循环中为不同的元素绑定事件,事件回调函数里如果调用了跟循环相关的变量,则这个变量取循环的最后一个值。
由于绑定的回调函数是一个匿名函数,所以上面的代码中, 这个匿名函数是一个闭包,携带的作用域为外层作用域(也就是for里面的作用域),当事件触发的时候,作用域中的变量已经随着循环走到最后了。
还有一点就是,事件是需要触发的,而绝大多数情况下,触发的时候循环已经结束了,所以循环相关的变量就是最后一次的取值。
要实现点击li,alert出li的索引值,需要将上面的代码进行以下的修改:
&ul id="test"&
&li&第一个&/li&
&li&第二个&/li&
&li&第三个&/li&
&li&第四个&/li&
var nodes=document.getElementsByTagName("li");
for(var i=0;i&nodes.i++){
(function(e){
nodes[i].onclick=function(){
解决思路: 增加若干个对应的闭包域空间(这里采用的是匿名函数),专门用来存储原先需要引用的内容(下标)。
当立即执行函数执行的时候,e 值不会被销毁,因为它的里面有个匿名函数(也可以说是因为闭包的存在,所以变量不会被销毁)。执行后,e 值 与全局变量 i 的联系就切断了,
也就是说,执行的时候,传进的 i 是多少,立即执行函数的 e 就是多少,但是 e 值不会消失,因为匿名函数的存在。
也可以用下面的解法,原理是一样的:
&ul id="test"&
&li&第一个&/li&
&li&第二个&/li&
&li&第三个&/li&
&li&第四个&/li&
var nodes=document.getElementsByTagName('li');
for(var i = 0; i&nodes.i++){
(function(){
var temp =
nodes[i].onclick = function () {
alert(temp);
1、造成内存泄露
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,所以只有在绝对必要时再考虑使用闭包。
2、在闭包中使用this也可能会导致一些问题。
代码示例:来源于《js高级程序设计3》;
其实我们的目的是想alert出object里面的name
var name="The Window";
var object={
name:"My Object",
getNameFunc:function(){
return function(){
return this.
alert(object.getNameFunc()()); // The Window
因为在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window。
每个函数在被调用时,都会自动取的两个特殊变量:this和 arguments。内部函数在搜索这两个变量时,只会搜索到其活动对象为止。也就是说,里面的return function只会搜索
到全局的this就停止继续搜索了。因为它永远不可能直接访问外部函数中的这两个变量。
稍作修改,把外部作用域中的this对象保存在一个闭包能够访问的变量里。这样就可以让闭包访问该对象了。
var name="The Window";
var object={
name:"My Object",
getNameFunc:function(){
return function(){
return that.
alert(object.getNameFunc()()); // My Object
我们把this对象赋值给了that变量。定义了闭包之后闭包也可以访问这个变量。因此,即使在函数返回之后,that也仍引用这object,所以调用object.getNameFunc()()就返回 “My Object”了。
当在函数内部定义了其他函数,就创建了闭包。闭包有权访问包含函数内部的所有变量。
闭包的作用域包含着它自己的作用域、包含函数的作用域和全局作用域。
当函数返回一个闭包时,这个函数的作用域会一直在内存中保存到闭包不存在为止。
使用闭包必须维护额外的作用域,所有过度使用它们可能会占用大量的内存
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持脚本之家!
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具浅谈JavaScript for循环 闭包
&更新时间:日 08:53:35 & 投稿:jingxian
下面小编就为大家带来一篇浅谈JavaScript for循环 闭包。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
有个网友问了个问题,如下的html,为什么每次输出都是5,而不是点击每个p,就alert出对应的1,2,3,4,5。
&meta http-equiv="Content-Type" content="text/ charset=utf-8" /&
&title&闭包演示&/title&
&script type="text/javascript"&
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
pAry[i].onclick = function() {
&body onload="init();"&
&p&产品一&/p&
&p&产品二&/p&
&p&产品三&/p&
&p&产品四&/p&
&p&产品五&/p&
解决方式有以下几种
1、将变量 i 保存给在每个段落对象(p)上
function init() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
pAry[i].i =
pAry[i].onclick = function() {
alert(this.i);
2、将变量 i 保存在匿名函数自身
function init2() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
(pAry[i].onclick = function() {
alert(arguments.callee.i);
3、加一层闭包,i以函数参数形式传递给内层函数
function init3() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
(function(arg){
pAry[i].onclick = function() {
alert(arg);
})(i);//调用时参数
4、加一层闭包,i以局部变量形式传递给内存函数
function init4() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
(function () {
var temp =//调用时局部变量
pAry[i].onclick = function() {
alert(temp);
5、加一层闭包,返回一个函数作为响应事件(注意与3的细微区别)
function init5() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
pAry[i].onclick = function(arg) {
return function() {//返回一个函数
alert(arg);
6、用Function实现,实际上每产生一个函数实例就会产生一个闭包
function init6() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
pAry[i].onclick = new Function("alert(" + i + ");");//new一次就产生一个函数实例
7、用Function实现,注意与6的区别
function init7() {
var pAry = document.getElementsByTagName("p");
for( var i=0; i&pAry. i++ ) {
pAry[i].onclick = Function('alert('+i+')')
以上就是小编为大家带来的浅谈JavaScript for循环 闭包全部内容了,希望大家多多支持脚本之家~
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具对象的动态特性是指:在对象创建出来之后,为对象添加新的属性或者方法。
给对象添加属性和方法有两种:
使用点语法给对象添加属性和方法
var obj = {
name: "kong",
obj.hobby = "runing";
obj.eat = function(){
console.log("开开心心的大吃!")
console.log(obj);
obj.eat();
如果给代码做些变化呢
obj.name = "diligentkong"
console.log(obj.name)
**使用点语法进行赋值的时候,如果对象存在该属性,是修改操作;
如果对象不存在该属性,是给该对象新增属性并且赋值**
使用中括号[]的方法
对象名[属性名]
注意:这里的属性名是字符串
通过对象名[属性名]的方式可以做到:
1.获取对象的属性值
2.修改对象的属性值
3.为对象新增属性并赋值
获取对象的属性:这是获取obj的name属性
console.log(obj["name"]);
修改对象的属性值,将obj对象的name属性的值修改为kongkong
obj["name"] = "kongkong";
console.log(obj["name"]);
obj["sing"] = {
singer : "张信哲"
console.log(obj["sing"]);
obj["drink"]=function(){
console.log("我喜欢和白开水");
obj[drink]();
这里要说一下in关键字
in关键字的用法
1.在for..in 循环中遍历对象的键
2.判断属性是否存在对象中
var obj = {
name:'kong',
for (var k in obj) {
console.log(k);
console.log(typeof k);
通过以上可以发现 对象的键为string字符串类型
也就是说 使用in关键字的时候,属性名称为字符串类型,需要用引号引起来
var paraName = "name";
var isExsit = paraName in
console.log(isExsit); // true
简单写成:
console.log("hobby" in obj);
在混入式继承关系上,如果要把一个对象的属性和方法 拿过来用到另一个独享上,要使用[]的方式获取属性、添加属性。若是使用点语法,那么会把k当做变量,而不是对象的键。看例子
//当前没有的属性和方法,别人有,拿过来用 ,就是继承(继承后续会解释的)
var obj = {
name :"diligentkong",
sayHello :function () {
console.log("Hello world");
o[k] = obj[k];
console.log(o);
in 关联数组
var arr=[2,4,6,8,10];
console.log(0 in arr); // 输出true
刚才提到 对象的键是字符串类型,为什么在关联数组的时候,打印输出的是true呢?
因为 in关键字操作数组的时候判断的是索引是否存在而不是值,当索引不是字符串的时候,会做一个隐式转换,将0 修改为”0”
console.log("0" in arr); // true
也就是console.log(0 in arr); &=&console.log("0" in arr); // true
如何判断数组中是否存在指定的值
for循环 如果找到了就输出
返回值为指定的数对应的索引,如果没有找到 返回-1
console.log(arr.indexOf(9));
delete关键字
1.delete关键字可以用来删除对象的属性,还有未使用var声明的变量
2.delete关键字有返回值 用来表示删除属性是否成功
3.如果删除的是不存在的属性,返回值为true
4.如果删除的属性存在原型当中,那么返回值为true,但是并未删除
自己对号入座吧!
var obj = {
name : "kong",
console.log(obj.name);
var result = delete obj.
console.log(obj.name, result);
// undefined true
num1 = 100;
console.log(num1); //100
result = delete num1;
console.log(window.num1, result); // undefined true
var num = 10;
var result = delete
console.log(result);
var result=
delete obj.
console.log(result); //true
console.log(obj.toString()); //[object Object]
var result = delete obj.toS
console.log(result); //true
console.log(obj.toString());//[object Object]
给一个对象添加属性和方法的三种方案简单比较
下午刚好没什么事情,作为有追求的程序员当然要搞点事情了,于是便把给对象添加属性和方法的几种常用方法总结了一下,不是很全面,只是自己的一点总结。
给一个对象添加属性和方法的三种方案...
函数:原型
每一个构造函数都有一个属性叫做原型(prototype,下面都不再翻译,使用其原文)。这个属性非常有用:为一个特定类声明通用的变量或者函数。
prototype的定义
给对象添加属性
1 Object 对象:Object是所有对象的基础,任何其他对象都是从Object扩展而来,或者说是继承。这一切都是由“原型”来完成。
2 原型对象:原型是对象的一个属性,也就是...
javascript是一种动态语言,不管你是否接受,它就是这样的,有些东西你必须接受它,才可以享受它提供的服务。
看书籍看的多了,也渐渐有了自己的看法。
Javascript在对象生成后,...
http://blog.csdn.net/ls/article/details/,自定义对象。 根据JS的对象扩展机制,用户可以自定义JS对象,这与Java语言有类似...
例如要给对象textObj添加个'selected'的新属性,可以这样来写:
var textObj = {};
textObj['selected'] = 'true';
console.lo...
JS 对象属性访问的2种方式和用途
问题起源:
在学习JS的过程中遇到一道题目“判断一个字符串中出现次数最多的字符,统计这个次数”,在网上查到一个用对象的方法解题,看完表示一脸懵逼。对代码中o[char]不能理解。
代码如下:
使用对象字面量创建对象
今天在学习《js高程》时看到了使用对象字面量创建对象的表示法,了解到对象字面变量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程,举一个简单的例子var person = {name...
js 定义属性 以及 getter 和 setter
今天说一下js 的属性设置,ES5中定义了两种属性,数据属性和访问器属性(getter 和 setter)下面我总结了一些数据属性
和 访问器属性的一些知识点。一、数据属性数据属性有四个描述其行为的...
没有更多推荐了,其他回答(3)
JavaScript中的闭包是访问了外部变量,会导致外部变量不能被垃圾回收。
其他编译类型的属性封装,都是编译器的检查规则,不存在跨作用域的问题。
园豆:35905
园豆:1977
园豆:35905
一般的编程语言呢?一个函数或者一段过程,它只管输入和输出,至于处理过程它不管的(外面无法访问里面),因为在处理过程中使用过的材料(变量),用它就销毁了。
但是有些编程语言呢?它还关注处理的过程。外面 可以访问里面的变量。
园豆:1977
函数内部可以访问到外部变量叫做闭包。全局函数相对全局变量就是个闭包,闭包变量会一直存储于内存。一般来说都是用(function(){})();这种形式封装代码,像一些插件什么的。我三年了理解也不深,表达也表达不是很明白。
清除回答草稿
&&&您需要以后才能回答,未注册用户请先。

我要回帖

更多关于 闭包有什么特性 的文章

 

随机推荐