我一直在使用Javascript string.match(*regex*)
函数来解析navigator.userAgent
字符串。
仅供参考,根据MDN& W3schools:
“match()方法在字符串中搜索与正则表达式的匹配,并以数组对象的形式返回匹配项。”
我首先解析一次以获取基本字符串所需的字符串:
var userAgent = navigator.userAgent;
var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);
这给了我以下输出(这是一个数组)
Mozilla/5.0
(Macintosh; Intel Mac OS X 10_10_3)
AppleWebKit/537.36
(KHTML, like Gecko)
Chrome/41.0.2272.76
Safari/537.36
然后我在for循环中解析 Navigator / Version 类型字符串
for (var i = 0; i < splitted.length; i++ ) {
var str = splitted[i];
if (str[0] == '(') {
} else {
var name = str.match(/[^\/]+/i);
var version = str.match(/[0-9|\.]+/i);
}
但是,非常令人惊讶,即使我得到了理想的结果,我得到 name 的字符串对象和版本的数组对象
怎么可能呢?
以下是代码片段(fiddle):
var userAgent = navigator.userAgent;
var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);
var outputDiv = document.getElementById("log");
for (var i = 0; i < splitted.length; i++ ) {
var str = splitted[i];
if (str[0] == '(') {
} else {
var name = str.match(/[^\/]+/i);
var version = str.match(/[0-9|\.]+/i);
outputDiv.innerHTML += name.toString() + " is a " + typeof(name) + "<br>";
outputDiv.innerHTML += version.toString() + " is a " + typeof(version) + "<br>";
}
};
<div id="log"></div>
---更新---
感谢 FactoryAidan 的答案,这是一个范围问题。
结论:在命名全局变量时要小心:)
答案 0 :(得分:5)
这是因为您使用name
作为变量。这是一个全局浏览器窗口变量,本身就是一个字符串,不能存储为数组
即使您使用var name =
重新声明它,您仍然在全球范围内。因此name
(又名window.name
)只保留您分配给它的最后一个值。
您可以在空白页面上使用以下内容对此进行测试,而无需定义任何变量:
console.log(name===window.name) // Returns true
console.log(name,window.name) // Returns 'Safari Safari' for my browser
name
更改为其他如果您将name
变量更改为只有一个不同的名称,例如my_name
,则会将.match()
的结果存储为数组。
var my_name = str.match(/[^\/]+/i);
var version = str.match(/[0-9|\.]+/i);
console.log(typeof my_name, my_name instanceof Array) // Returns object, true
这是包含在函数内的确切代码,并返回正确的变量类型:
function getBrowserStuff(){
var userAgent = navigator.userAgent;
var splitted = userAgent.match(/[(][^)]+[)]|\w+\/\S+/ig);
for (var i = 0; i < splitted.length; i++ ) {
var str = splitted[i];
if (str[0] == '(') {
} else {
var name = str.match(/[^\/]+/i);
var version = str.match(/[0-9|\.]+/i);
console.log('Name','Typeof '+(typeof name), 'IsArray '+(name instanceof Array),name)
console.log('Version','Typeof '+(typeof version),'IsArray '+(version instanceof Array),version)
}
}
return 'whatever'
}
getBrowserStuff()
将变量name
更改为my_name
或包装代码,如上面的函数返回:
Name Typeof object IsArray true ["Mozilla"]
Version Typeof object IsArray true ["5.0"]
Name Typeof object IsArray true ["AppleWebKit"]
Version Typeof object IsArray true ["600.3.18"]
Name Typeof object IsArray true ["Version"]
Version Typeof object IsArray true ["8.0.3"]
Name Typeof object IsArray true ["Safari"]
Version Typeof object IsArray true ["600.3.18"]
之前它返回的地方:
Name Typeof string IsArray false Mozilla
Version Typeof object IsArray true ["5.0"]
Name Typeof string IsArray false AppleWebKit
Version Typeof object IsArray true ["600.3.18"]
Name Typeof string IsArray false Version
Version Typeof object IsArray true ["8.0.3"]
Name Typeof string IsArray false Safari
Version Typeof object IsArray true ["600.3.18"]
答案 1 :(得分:0)
这是不可能的,或者是您实施的错误。
根据ECMAScript 5.1规范,match
的行为如下:
15.5.4.10 String.prototype.match (regexp)
使用参数 regexp 调用
match
方法时, 采取以下步骤:
- 调用CheckObjectCoercible将此值作为参数传递。
- 让 S 成为调用ToString的结果,并将此值作为其参数。
- 如果Type( regexp )为Object且 regexp 的[[Class]]内部属性的值为&#34; {{1然后让 rx 成为。&#34; 的regexp ;
- 否则,让 rx 成为一个新的RegExp对象,就像表达式
RegExp
regexpnew RegExp(
一样,其中)
是标准 具有该名称的内置构造函数。- 让 global 成为使用参数&#34;
RegExp
&#34;调用 rx 的[[Get]]内部方法的结果。- 让 exec 成为标准内置函数
global
(see 15.10.6.2)- 如果 global 不是 true ,那么
- 使用 rx 返回调用 exec 的[[Call]]内部方法的结果作为包含<的此值和参数列表EM>取值
- 否则,全球 true
醇>
- 使用参数&#34;
RegExp.prototype.exec
&#34;调用 rx 的[[Put]]内部方法和0。- 让 A 成为一个新的数组,就像表达式
lastIndex
一样,其中new Array()
是标准的内置构造函数 名称- 让 previousLastIndex 为0。
- 让 n 为0。
- 让 lastMatch 为 true 。
- 重复,而 lastMatch true
- 让结果是用 rx 调用 exec 的[[Call]]内部方法的结果 this 值和参数列表 包含 S 。
- 如果结果 null ,则将 lastMatch 设置为 false 。
- 否则,结果不是 null
- 让 thisIndex 成为使用参数&#34;
Array
&#34;调用 rx 的[[Get]]内部方法的结果。- 如果 thisIndex = previousLastIndex 那么
- 使用参数&#34;
lastIndex
&#34;调用 rx 的[[Put]]内部方法和 thisIndex +1。- 将 previousLastIndex 设置为 thisIndex +1。
- 否则,将 previousLastIndex 设置为 thisIndex 。
- 让 matchStr 成为使用参数&#34;
lastIndex
&#34;调用结果的[[Get]]内部方法的结果。- 使用参数ToString( n )调用 A 的[[DefineOwnProperty]]内部方法,Property Descriptor {[[Value]]: matchStr ,[[Writable]]: true ,[[Enumerable]]: true ,[[可配置]]: true }, false 。
- 增加 n 。
- 如果 n = 0,则返回 null 。
- 返回 A 。
因此,对于全局正则表达式,唯一可能的返回值是 null 或 A ,这是一个数组。
对于非全局的,返回调用RegExp.prototype.exec
的结果。但它也会返回一个数组或 null :
对常规执行 string 的正则表达式匹配 表达式并返回一个包含结果的Array对象 如果 string 不匹配,则匹配或 null 。