По крайней мере, вплоть до CSS3, включая CSS3, вы не можете выбрать это. Но это может быть сделано довольно легко в настоящее время в JS, вам просто нужно добавить немного ванильного JavaScript, обратите внимание, что код довольно короткий.
cells = document.querySelectorAll('div');
[].forEach.call(cells, function (el) {
//console.log(el.nodeName)
if (el.hasChildNodes() && el.firstChild.nodeName=="A") {
console.log(el)};
});
<div>Peter</div>
<div><a href="#">Jackson link</a></div>
<div>Philip</div>
<div><a href="#">Pullman link</a></div>
Я думаю, что самый простой способ проверить, является ли эта функция классом ES6, - проверить результат метода .toString()
. Согласно es2015 spec :
Строковое представление должно иметь синтаксис FunctionDeclaration FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, ClassExpression, ArrowFunction, MethodDefinition или GeneratorMethod в зависимости от по фактическим характеристикам объекта
blockquote>Таким образом, функция проверки выглядит довольно просто:
function isClass(func) { return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func)); }
Определить некоторые эталонные показатели производительности на разных подходах, упомянутых в этом потоке, вот обзор:
Native Class - метод реквизита (быстрее всего на 56x на больших примерах , и 15x по тривиальным примерам):
function isNativeClass (thing) {
return typeof thing === 'function' && thing.hasOwnProperty('prototype') && !thing.hasOwnProperty('arguments')
}
Это работает, потому что верно следующее:
> Object.getOwnPropertyNames(class A {})
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(class A { constructor (a,b) {} })
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(class A { constructor (a,b) {} a (b,c) {} })
[ 'length', 'name', 'prototype' ]
> Object.getOwnPropertyNames(function () {})
[ 'length', 'name', 'arguments', 'caller', 'prototype' ]
> Object.getOwnPropertyNames(() => {})
> [ 'length', 'name' ]
Метод Native Class - String (быстрее, чем метод regex by by около 10%):
/**
* Is ES6+ class
* @param {any} value
* @returns {boolean}
*/
function isNativeClass (value /* :mixed */ ) /* :boolean */ {
return typeof value === 'function' && value.toString().indexOf('class') === 0
}
Это также может быть полезно для определения обычного класса:
// Character positions
const INDEX_OF_FUNCTION_NAME = 9 // "function X", X is at index 9
const FIRST_UPPERCASE_INDEX_IN_ASCII = 65 // A is at index 65 in ASCII
const LAST_UPPERCASE_INDEX_IN_ASCII = 90 // Z is at index 90 in ASCII
/**
* Is Conventional Class
* Looks for function with capital first letter MyClass
* First letter is the 9th character
* If changed, isClass must also be updated
* @param {any} value
* @returns {boolean}
*/
function isConventionalClass (value /* :any */ ) /* :boolean */ {
if ( typeof value !== 'function' ) return false
const c = value.toString().charCodeAt(INDEX_OF_FUNCTION_NAME)
return c >= FIRST_UPPERCASE_INDEX_IN_ASCII && c <= LAST_UPPERCASE_INDEX_IN_ASCII
}
Я также рекомендую проверить my typechecker
package , который включает в себя варианты использования выше - с помощью метода isNativeClass
, isConventionalClass
и метода isClass
, который проверяет оба типа.
caller
или arguments
в класс после факта, так как оба являются ограниченными функциями функции i>, и попытка их добавления выдает TypeError
.
– Pierre Arnaud
2 December 2015 в 05:58
['length', 'name', 'prototype']
. Таким образом, это не работает для меня .
– Pierre Arnaud
2 December 2015 в 06:05
arguments
или caller
. То есть (() => {}).hasOwnProperty('arguments')
возвращает true.
– Dave W.
21 March 2017 в 04:59
isClass
из пакета typechecker
который проверяет как родной, так и обычный классы.
– balupton
22 March 2017 в 02:32
Я провел некоторое исследование и выяснил, что объект прототипа [ spec 19.1.2.16 ] классов ES6, по-видимому, не записывается , неперечислимый , неконфигурируемый .
Вот способ проверки:
class F { }
console.log(Object.getOwnPropertyDescriptor(F, 'prototype'));
// {"value":{},"writable":false,"enumerable":false,"configurable":false
Регулярная функция по умолчанию доступна для записи , неперечислимые , неконфигурируемые .
function G() { }
console.log(Object.getOwnPropertyDescriptor(G, 'prototype'));
// {"value":{},"writable":true,"enumerable":false,"configurable":false}
ES6 Fiddle: http://www.es6fiddle.net/i7d0eyih/
Таким образом, дескриптор класса ES6 всегда будет иметь эти свойства на false и будет вызывать ошибку, если вы попытаетесь определить дескрипторы.
// Throws Error
Object.defineProperty(F, 'prototype', {
writable: true
});
Однако с помощью обычной функции вы все равно можете определить эти дескрипторы.
// Works
Object.defineProperty(G, 'prototype', {
writable: false
});
Это не очень что дескрипторы изменяются на регулярные функции, поэтому вы, вероятно, можете использовать это, чтобы проверить, является ли это классом или нет, но, конечно, это не настоящее решение.
Метод @alexpods для подбора функции и проверки для ключевого слова class, вероятно, является лучшим решением на данный момент.
F.prototype
устанавливается, когда оценивается тело класса, которое описано здесь: people.mozilla.org/~jorendorff/… ; дескриптор свойства для Object.prototype
- это нечто совершенно другое (хотя иногда он влияет на связанный выше алгоритм). Этот алгоритм слишком сложный для меня, чтобы быстро увидеть, правы ли вы в F.prototype
, всегда будучи неперечислимыми, не записываемыми и т. Д. Но если кто-то хочет изучить его больше, это то, где они должны проверять.
– Ethan
19 October 2015 в 05:53
Глядя на скомпилированный код, сгенерированный Babel , я думаю, что вы не можете определить, используется ли функция как класс. В то время JavaScript не имел классов, и каждый конструктор был просто функцией.
Код ES6:
// ES6
class A{}
ES5, сгенерированный Babel :
// ES5
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var A = function A() {
_classCallCheck(this, A);
};
Конечно, если вы используете соглашения о кодировании, вы можете проанализировать функцию (класс) и проверить, начинается ли это имя с заглавной буквы.
function isClass(fn) {
return typeof fn === 'function' && /^(?:class\s+|function\s+(?:_class|_default|[A-Z]))/.test(fn);
}
EDIT:
Браузеры, которые уже поддерживают ключевое слово класса, могут использовать его при разборе. В противном случае вы застряли с заглавной буквой.
EDIT:
Как отметил Балуптон, Бабель генерирует function _class() {}
для анонимных классов.
Добавлено _default
в регулярное выражение, чтобы обнаружить такие классы, как export default class {}
g13] BabelJS находится в стадии разработки, и нет гарантии, что они не изменят имена функций по умолчанию в этих случаях. На самом деле, вы не должны полагаться на это.
function _class () {}
- исходный код function a ( ) { return class {} && class {} }
, регулярное выражение может быть соответствующим образом изменено.
– balupton
26 August 2015 в 22:02
return typeof fn === 'function' && /^(?:class|function (?:[A-Z]|_class))/.test(fn)
– balupton
26 August 2015 в 22:08
export default class {}
, возможно, просто проверка на _classCallCheck
является лучшим вариантом.
– balupton
26 August 2015 в 22:14
_classCallCheck
во всей функции является излишним и имеет незначительный эффект. Проверка начального количества имен в столице - слабое звено здесь
– Tamas Hegedus
26 August 2015 в 22:19
, если я правильно понял ES6, используя class
, имеет такой же эффект, как если бы вы вводили синтаксическую ошибку
var Foo = function(){}
var Bar = function(){
Foo.call(this);
}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.constructor = Bar;
при вводе MyClass()
без keyword new
, чтобы предотвратить загрязнение глобального пространства с помощью переменные, предназначенные для использования объектом.
var MyClass = function(){this.$ = "my private dollar"; return this;}
, если у вас есть
// $ === jquery
var myObject = new MyClass();
// $ === still jquery
// myObject === global object
, но если вы делаете
var myObject = MyClass();
// $ === "My private dollar"
, поскольку this
в Конструктор, называемый функцией, относится к глобальному объекту, но при вызове с ключевым словом new
Javascript сначала создает новый пустой объект, а затем вызывает на нем конструктор.
io.js
с флагомharmony
или в Chrome Canary – alexpods 17 March 2015 в 09:24