基于JavaScript分析property 和 attribute,JSP毕业设计参考题目

// 这个新的fn会将value function作为回调函数传递给到老的处理方法

} else {

bulk = fn;

fn = function( elem, key, value ) {

return bulk.call( jQuery( elem ), value );

};

}

}

if ( fn ) { // 利用处理方法fn对元素集合中每个元素进行处理

for ( ; i < length; i++ ) {

fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );

// 如果value是一个funciton,那么首先利用这个函数返回一个值并传入fn

}

}

}

return chainable ?

elems : // 如果是链式调用,就返回元素集合

// Gets

bulk ?

fn.call( elems ) :

length ? fn( elems[0], key ) : emptyGet;

};

access方法虽然不长,但是非常绕,要完全读懂并不简单,因此可以针对jQuery.fn.attr的调用来简化access。

jQuery.fn.attr/ jQuery.fn.prop 中的access调用

$().attr的调用方式:

  • $().attr( propertyName ) // 获取单个属性

  • $().attr( propertyName, value ) // 设置单个属性

  • $().attr( properties ) // 设置多个属性

  • $().attr( propertyName, function ) // 对属性调用回调函数

prop的调用方式与attr是一样的,在此就不重复列举。为了简单起见,在这里只对第一和第二种调用方式进行研究。

调用语句:

access( this, jQuery.attr, name, value, arguments.length > 1 );

简化的access:

// elems 当前的jQuery对象,可能包含多个DOM对象

// fn jQuery.attr方法

// name 属性名

// value 属性的值

// chainable 如果value为空,则chainable为false,否则chainable为true

var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {

var i = 0, // 迭代计数

length = elems.length, // 属性数量

bulk = false; // key != null

if ( value !== undefined ) { // 如果value不为空,则为设置新值,否则返回该属性的值

chainable = true;

raw = true; // value不是function

if ( fn ) { // fn为jQuery.attr

for ( ; i < length; i++ ) {

fn( elems[i], key, value); // jQuery.attr(elems, key, value);

}

}

}

if(chainable) { // value不为空,表示是get

return elems; // 返回元素实现链式调用

} else {

if(length) { // 如果元素集合长度不为零,则返回第一个元素的属性值

return fn(elems[0], key); // jQuery.attr(elems[0], key);

} else {

return emptyGet; // 返回一个默认值,在这里是undefined

}

}

};

通过简化代码,可以知道,access的作用就是遍历上一个$调用得到的元素集合,对其调用fn函数。在jQuery.attr和jQuery.prop里面,就是利用access来遍历元素集合并对其实现对attribute和property的控制。access的源码里面有多段条件转移代码,看起来眼花缭乱,其最终目的就是能够实现对元素集合的变量并完成不同的操作,复杂的代码让jQuery的接口变得更加简单,能极大提高代码重用性,意味着减少了代码量,提高代码的密度从而使JS文件大小得到减少。

这些都是题外话了,现在回到 ( ) . a t t r 和 ().attr和 ().attr().prop的实现。总的说,这两个原型方法都利用access对元素集进行变量,并对每个元素调用jQuery.prop和jQuery.attr方法。要注意,这里的jQuery.prop和jQuery.attr并不是原型链上的方法,而是jQuery这个对象本身的方法,它是使用jQuery.extend进行方法扩展的(jQuery.fn.prop和jQuery.fn.attr是使用jQuery.fn.extend进行方法扩展的)。

下面看看这两个方法的源码。

jQury.attr

jQuery.extend({

attr: function( elem, name, value ) {

var hooks, ret,

nType = elem.nodeType; // 获取Node类型

// 如果 elem是空或者NodeType是以下类型

// 2: Attr, 属性, 子节点有Text, EntityReference

// 3: Text, 元素或属性中的文本内容

// 8: Comment, 注释

// 不执行任何操作

if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {

return;

}

// 如果支持attitude方法, 则调用property方法

if ( typeof elem.getAttribute === strundefined ) {

return jQuery.prop( elem, name, value );

}

// 如果elem的Node类型不是元素(1)

if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {

name = name.toLowerCase();

// 针对浏览器的兼容性,获取钩子函数,处理一些特殊的元素

hooks = jQuery.attrHooks[ name ] ||

( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );

}

if ( value !== undefined ) { // 如果value不为undefined,执行"SET"

if ( value === null ) { // 如果value为null,则移除attribute

jQuery.removeAttr( elem, name );

} else if ( hooks && “set” in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {

return ret; // 使用钩子函数

} else { // 使用Dom的setAttribute方法

elem.setAttribute( name, value + “” ); // 注意,要将value转换为string,因为所有attribute的值都是string

return value;

}

// 如果value为undefined,就执行"GET"

} else if ( hooks && “get” in hooks && (ret = hooks.get( elem, name )) !== null ) {

return ret; // 使用钩子函数

} else {

ret = jQuery.find.attr( elem, name ); // 实际上调用了Sizzle.attr,这个方法中针对兼容性问题作出处理来获取attribute的值

// 返回获得的值

return ret == null ?

undefined :

ret;

}

},

});

从代码可以发现,jQuery.attr调用的是getAttribute和setAttribute方法。

jQeury.prop

jQuery.extend({

prop: function( elem, name, value ) {

var ret, hooks, notxml,

nType = elem.nodeType;

// 过滤注释、Attr、元素文本内容

if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {

return;

}

notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

if ( notxml ) { // 如果不是元素

name = jQuery.propFix[ name ] || name; // 修正属性名

hooks = jQuery.propHooks[ name ]; // 获取钩子函数

}

if ( value !== undefined ) { // 执行"SET"

return hooks && “set” in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?

ret : // 调用钩子函数

( elem[ name ] = value ); // 直接对elem[name]赋值

} else { // 执行"GET"

return hooks && “get” in hooks && (ret = hooks.get( elem, name )) !== null ?

ret : // 调用钩子函数

elem[ name ]; // 直接返回elem[name]

}

},

});

jQuery.prop则是直接对DOM对象上的property进行操作。

通过对比jQuery.prop和jQuery.attr可以发现,前者直接对DOM对象的property进行操作,而后者会调用setAttribute和getAttribute方法。setAttribute和getAttribute方法又是什么方法呢?有什么效果?

setAttribute和getAttribute

基于之前测试使用的输入框,执行如下代码:

in1.setAttribute(‘value’, ‘new attr from setAttribute’);

console.log(in1.getAttribute(‘value’)); // ‘new attr from setAttribute’

console.log(in1.value); // ‘new attr from setAttribute’

console.log(in1.attributes.value); // ‘value=​"new attr from setAttribute"’,实际是一个Attr对象

执行完setAttribute以后,就如同直接更改attributes中的同名属性;

而getAttribute的结果与访问property的结果一模一样,而不会像直接访问attritudes那样返回一个Attr对象。

特殊的例子


href

然而,是不是所有标签,所有属性都维持保持这样的特性呢?下面我们看看href这个属性/特性。

首先在html中创建一个标签:

在JS脚本中执行如下代码:

console.log(a1.href); // ‘file:///D:/GitHub/JS/html/test_01/page_1.html’

console.log(a1.getAttribute(‘href’)); // ‘page_1.html’

可以看到,property中保存的是绝对路径,而attribute中保存的是相对路径。那么,如果更改了这些值会发生什么情况呢?

更改attribute:

a1.setAttribute(‘href’, ‘page_2.html’); // 相对路径

console.log(a1.href); // ‘file:///D:/GitHub/JS/html/test_01/page_2.html’

console.log(a1.getAttribute(‘href’)); // ‘page_2.html’

a1.setAttribute(‘href’, ‘/page_3.html’); // 根目录路径

console.log(a1.href); // ‘file:///D:/page_3.html’

console.log(a1.getAttribute(‘href’)); // ‘/page_3.html’

更改property:

a1.href = ‘home.html’; // 相对路径

console.log(a1.href); // ‘file:///D:/GitHub/JS/html/test_01/home.html’

console.log(a1.getAttribute(‘href’)); // ‘home.html’

a1.href = ‘/home.html’; // 根目录路径

console.log(a1.href); // ‘file:///D:/home.html’

console.log(a1.getAttribute(‘href’)); // ‘/home.html’

从这里可以发现,href是特殊的属性/特性,二者是双向绑定的,更改任意一方,都会导致另一方的的值发生改变。而且,这并不是简单的双向绑定,property中的href永远保存绝对路径,而attribute中的href则是保存相对路径。

看到这里,attribute和property的区别又多了一点,然而,这又让人变得更加疑惑了。是否还有其他类似的特殊例子呢?

id

尝试改变property中的id:

a1.id = ‘new_id’;

console.log(a1.id); // ‘new_id’

console.log(a1.getAttribute(‘id’)); // ‘new_id’

天呀,现在attribute中的id从property中的id发生了同步,数据方向变成了property <=> attribute

disabled

再来看看disabled这个属性,我们往第一个添加“disabled”特性:

// 此时input已经被禁用了

然后执行下面的代码:

console.log(in1.disabled); // true

in1.setAttribute(‘disabled’, false); // 设置attribute中的disabled,无论是false还是null都不会取消禁用

console.log(in1); // true

console.log(in1.getAttribute(‘disabled’)); // ‘false’

改变attributes中的disabled不会改变更改property,也不会取消输入栏的禁用效果。

如果改成下面的代码:

console.log(in1.disabled); // true

in1.disabled = false; // 取消禁用

console.log(in1.disabled); // false

console.log(in1.getAttribute(‘disabled’)); // null,attribute中的disabled已经被移除了

又或者:

console.log(in1.disabled); // true

in1.removeAttribute(‘disabled’); // 移除attribute上的disabled来取消禁用

console.log(in1.disabled); // false

console.log(in1.getAttribute(‘disabled’)); // null,attribute中的disabled已经被移除了

可以发现,将property中的disabled设置为false,会移除attributes中的disabled。这样数据绑定又变成了,property<=>attribute;

所以property和attritude之间的数据绑定问题并不能单纯地以“property<-attribute”来说明。

总结

分析了这么多,对property和attribute的区别理解也更深了,在这里总结一下:

创建

  • DOM对象初始化时会在创建默认的基本property;

  • 只有在HTML标签中定义的attribute才会被保存在property的attributes属性中;

  • attribute会初始化property中的同名属性,但自定义的attribute不会出现在property中;

  • attribute的值都是字符串

数据绑定

  • attributes的数据会同步到property上,然而property的更改不会改变attribute;

  • 对于value,class这样的属性/特性,数据绑定的方向是单向的,attribute->property

  • 对于id而言,数据绑定是双向的,attribute<=>property

  • 对于disabled而言,property上的disabled为false时,attribute上的disabled必定会并存在,此时数据绑定可以认为是双向的;

使用

  • 可以使用DOM的setAttribute方法来同时更改attribute;

  • 直接访问attributes上的值会得到一个Attr对象,而通过getAttribute方法访问则会直接得到attribute的值;

  • 大多数情况(除非有浏览器兼容性问题),jQuery.attr是通过setAttribute实现,而jQuery.prop则会直接访问DOM对象的property;

到这里为止,得出,property是DOM对象自身就拥有的属性,而attribute是我们通过设置HTML标签而给之赋予的特性,attribute和property的同名属性/特性之间会产生一些特殊的数据联系,而这些联系会针对不同的属性/特性有不同的区别。

事实上,在这里,property和attribute之间的区别和联系难以用简单的技术特性来描述,我在StackFlow上找到如下的回答,或者会更加接近于真正的答案:

These words existed way before Computer Science came around.

Attribute is a quality or object that we attribute to someone or something. For example, the scepter is an attribute of power and statehood.

Property is a quality that exists without any attribution. For example, clay has adhesive qualities; or, one of the properties of metals is electrical conductivity. Properties demonstrate themselves though physical phenomena without the need attribute them to someone or something. By the same token, saying that someone has masculine attributes is self-evident. In effect, you could say that a property is owned by someone or something.

To be fair though, in Computer Science these two words, at least for the most part, can be used interchangeably - but then again programmers usually don’t hold degrees in English Literature and do not write or care much about grammar books 😃.
最关键的两句话:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

part, can be used interchangeably - but then again programmers usually don’t hold degrees in English Literature and do not write or care much about grammar books 😃.
最关键的两句话:

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-RbJgTQnO-1712561150287)]
[外链图片转存中…(img-jmTrbnjx-1712561150288)]
[外链图片转存中…(img-sPSIa1Hs-1712561150288)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-vg5xnKud-1712561150289)]

  • 30
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值