как создать объект-оболочку, который действует как функция, подобная jquery

#javascript #jquery #html #css

#javascript #jquery #HTML #css

Вопрос:

Я не знаю, с чего начать, но то, что мне нужно или нужно, — это функция-оболочка для HTMLElement, поэтому я не расширяю класс HTMLElement, а создаю свой собственный объект, а затем проверяю has class, Чтобы узнать, есть ли у элемента класс и т. Д. И т. Д. Но мой код вообще не работает, в нем написано $ (…).hasClass не является функцией

 $ = function(a, b) {
  this.$el = document.querySelector(a);
  return this;
}

Object.assign($.prototype, {
  hasClass: function(selector) {
    return this.$el.classList.contains(selector);
  }
})

console.log($('#list').hasClass('list'));
 

Ответ №1:

Вы почти на месте — проблема в том, что автономное выражение

 $('#list')
 

будет иметь контекст вызова по умолчанию window ( this значение внутри $ функции). Если вы хотите создать экземпляр, который может использовать методы-прототипы, поместите new перед вызовом $ :

 const $ = function(a, b) {
  this.$el = document.querySelector(a);
}

Object.assign($.prototype, {
  hasClass: function(selector) {
    return this.$el.classList.contains(selector);
  }
})

console.log(new $('#list').hasClass('list'));
console.log(new $('#list2').hasClass('foo')); 
 <div id="list"></div>
<div id="list2" class="foo"></div> 

Если вы не хотите ставить new перед каждым вызовом, вы можете использовать Object.create inside $ :

 const $ = function(a, b) {
  const $obj = Object.create(proto);
  $obj.$el = document.querySelector(a);
  return $obj;
}

const proto = {
  hasClass: function(selector) {
    return this.$el.classList.contains(selector);
  }
};

console.log($('#list').hasClass('list'));
console.log($('#list2').hasClass('foo')); 
 <div id="list"></div>
<div id="list2" class="foo"></div> 

Я думаю, что способ, которым это делает jQuery, заключается в том, что внутренний прототип возвращаемого объекта $.fn , например:

 const $ = function(a, b) {
  const $obj = Object.create($.fn);
  $obj.$el = document.querySelector(a);
  return $obj;
};
$.fn = {
  hasClass: function(selector) {
    return this.$el.classList.contains(selector);
  }
};

console.log($('#list').hasClass('list'));
console.log($('#list2').hasClass('foo')); 
 <div id="list"></div>
<div id="list2" class="foo"></div> 

Комментарии:

1. Хорошо, но я не хочу каждый раз вставлять ключевое слово «new» перед $(«), так что для этого нужно что-то делать

2. Используйте Object.create , как во втором фрагменте

3. в нем говорится, что proto не определено

4. Нажмите кнопку «Выполнить фрагмент кода» в ответе, чтобы увидеть его в действии — здесь он работает просто отлично. Вы уверены, что вы определили proto в своем коде?

5. Одним из моих пунктов было использование Object.assign($.prototype, {}); а теперь вы его убрали

Ответ №2:

Альтернативный метод, выполняемый с функцией возврата внутри функции

 const $ = function(a, b) {
  var elem = document.querySelector(a);
  return {
    hasClass: function(selector) {
      return elem.classList.contains(selector);
    },
    addClass:function(cls){
      elem.classList.add(cls)
    }
  }
};

console.log($('#list').hasClass('list'));
console.log($('#list2').hasClass('foo'));
$('#list2').addClass('color_red'); 
 .color_red{
  color:red
} 
 <div id="list"></div>
<div id="list2" class="foo">hello</div>