js中的大坑
- 对象的原型的的定义
- 一个对象如果有length属性和splice属性就是伪数组
- js中函数也是对象,但是不能给他添加name属性,应为name属性为函数名
- 下面是我自己模仿的jQuery简易版(可以批量添加删除class)
对象的原型的的定义
1.下面是错误的
var o = new Object;
//下面这样写是错误的,这相当于重新给原型赋值为一个对象,相当于Object的一个实例,而不是o
o.prototype ={
init:function(){},
name:"",
age:""
}
console.log(o.porototype.constructor);//Object,这里应该返回o
2.下面是正确的操作
var o = new Object;
//下面是正确的添加原型属性的方法
o.prototype.init = function(){};
o.prototype.name = "";
o.prototype.age="";
console.log(o.prototype.constructor);//o,正确
一个对象如果有length属性和splice属性就是伪数组
下面是判断伪数组的方法
function isArraylike( obj ) {
var length = obj.length,
type = jQuery.type( obj );
if ( type === "function" || jQuery.isWindow( obj ) ) {
return false;
}
if ( obj.nodeType === 1 && length ) {
return true;
}
return type === "array" || length === 0 ||
typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}
js中函数也是对象,但是不能给他添加name属性,应为name属性为函数名
思考下面两个代码在控制台的输出结果
var a= function(){}; a.name;
输出
""
var a= function b(){}; a.name;
输出
"b"
下面是我自己模仿的jQuery简易版(可以批量添加删除class)
尝试理解下面的代码的含义
;(function (window,undefined) {
var $ = function (selector,contax,selectorRoot) {
return new $.fn.init(selector,contax,selectorRoot);
};
$.fn = $.prototype ={
//采用.prototype={}添加原型属性需要重新修正构造函数,否则构造函数会变成object
constructor:$,
length:0,
splice:function (num) {
[].splice.call(this,num);
},
map:function (fn) {
[].map.call(this,fn);
},
init:function (selector,contax,selectorRoot) {
if(!selector){
return this;
}
if(selector){
//将查询到的nodelist添加到$对象中,因为$有length和splice,所以是个伪数组(其实有length就是伪数组)
if(/^\#.+/.test(selector)){
//如果是查询id就不能用apply
[].push.call(this,this.find(selector));
}else{
[].push.apply(this,this.find(selector));
}
return this;
}
},
find:function (selector) {
if(/^\..+/.test(selector)){
return document.getElementsByClassName(selector.substr(1));
}else if(/^\#.+/.test(selector)){
return document.getElementById(selector.substr(1));
}else{
return document.getElementsByTagName(selector);
}
},
addClass:function (str) {
var reg = new RegExp('\\s*'+str+'\\s*');
//利用map属性对数组操作
this.map(function (a) {
if(!reg.test(a.className)){
a.className += ' '+str;
}
});
return this;
},
deleteClass:function (str) {
var reg = new RegExp('\\s*'+str+'\\s*');
this.map(function (a) {
if(reg.test(a.className)){
a.className = a.className.replace(reg,'');
}
});
return this;
}
}
$.extend = $.fn.extend = function () {
var deep=false,isArray=false,
src, clone, option, name, copy,
len = arguments.length,
//i永远指向新添加对象的参数位置
i=1,
//target为原有对象
target=arguments[0] || {};
//如果第一个参数为deep,那么就都往后移一位
if(typeof target === 'boolean'){
deep = target;
i=2;
target = arguments[1];
}
//target不是对象或函数对象的情况
if(typeof target !== 'object' && typeof target !== 'function'){
target = {};
}
//没有target的情况
if(i === len){
target =this;
i = i-1;
}
for(;i<len;i++){
option = arguments[i];
//判断option是否是null或者undefined
if(option != null){
for(name in option){
src = target[name];
copy = option[name];
//target已经有要添加的对象的情况
if(target === copy){
continue;
}
isArray = (copy instanceof Array);
if(deep && copy && (typeof copy ==='object' || isArray ) ){
if(isArray){
isArray = false;
clone = src && (src instanceof Array)?src:[];
}else{
clone = src && (typeof src === 'object')?src:{};
}
target[name]=$.extend(deep,clone,copy);
}else if(copy !== undefined){
target[name]=copy;
}
}
}
}
//返回添加后的对象
return target;
}
$.fn.init.prototype = $.fn;
window.$ = $;
}(window));