我的一个朋友在一些Javascript代码中发现了一些有趣的行为,我决定进一步调查.
比较
(function (x) {return x*x;}) > [1,2,3]
Run Code Online (Sandbox Code Playgroud)
返回true大多数主流浏览器(Firefox,Chrome,Opera和Safari)和falseIE9.对我来说,除了undefined没有办法说函数大于数组之外,没有这种比较的逻辑结果.
在ECMA脚本标准中读到它,它说>在对象上使用它的实际参数是在参数上调用ToNumber内部操作的结果.一些实验和进一步阅读告诉我,这与应用类型转换不同(Number) arg.阅读规范,我很难搞清楚这里发生了什么.
谁能让我知道这里发生了什么?
所以,我在定义什么new Object和Object做什么时看着ES5规范.出乎我的意料:
new Object描述了对象构造函数如何工作的整个算法 - 处理不同类型的值所发生的事情.基本上调用ToObject非对象 - 对象上的标识和构建在null和undefined上.Object在null和undefined中有一个特殊的第一步,它构建一个对象,然后调用对象ToObject上的基元和标识.在阅读了几次描述之后 - 它们看起来完全相同.但是,很明显,从规范中他们做了不同的事情.例如,在Array调用new Array中指定函数调用Array(…)等同于new Array(…)具有相同参数的对象创建表达式
那么 - 和之间有什么区别?为什么他们指定不同?new ObjectObject
ECMAScript允许我们定义getter或setter如下:
[文本/ JavaScript的]
var object = {
property: 7,
get getable() { return this.property + 1; },
set setable(x) { this.property = x / 2; }
};
Run Code Online (Sandbox Code Playgroud)
如果我正在使用课程,我可以解决:
[文本/ CoffeeScript的]
"use strict"
Function::trigger = (prop, getter, setter) ->
Object.defineProperty @::,
get: getter
set: setter
class Class
property: ''
@trigger 'getable', ->
'x'
member: 0
Run Code Online (Sandbox Code Playgroud)
但是,如果我想要什么定义上触发直接对象 - 不使用defineProperty/ - ies.我想做一些事情(它不是那样工作):
[文本/ X-伪的CoffeeScript]
object =
property: 'xhr'
get getable: 'x'
Run Code Online (Sandbox Code Playgroud)
它在JavaScript中运行没有任何问题,我不希望我的脚本在使用CoffeeScript时回退.难道没有办法像JavaScript/ECMAScript …
严格模式编译指示在ECMAScript5中有什么范围?
"use strict";
Run Code Online (Sandbox Code Playgroud)
我想这样做(主要是因为JSLint没有抱怨它):
"use strict";
(function () {
// my stuff here...
}());
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否会破坏其他代码.我知道我可以做到这一点,这将把pragma的范围扩展到函数...
(function () {
"use strict";
// my stuff here...
}());
Run Code Online (Sandbox Code Playgroud)
但JSLint抱怨它(当启用"严格"JSLint选项时),因为它认为您在启用"use strict"之前正在执行代码.
这是我的问题.如果我有fileA.js:
"use strict";
// do some stuff
Run Code Online (Sandbox Code Playgroud)
和fileB.js:
eval( somecodesnippet ); // disallowed by "use strict"
Run Code Online (Sandbox Code Playgroud)
然后将它们以相同的顺序包含在我的html页面中,将pragma限定为文件,还是将pragma放到fileB中,从而阻止eval执行?
在阅读dzone上发布的这篇文章时,我发现了一段最初由Marcus Lagergren在Twitter上发布的JavaScript片段.
以下代码显然打印字符串 "fail"
(![]+[])[+[]]+(![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]];
Run Code Online (Sandbox Code Playgroud)
这涉及隐式类型转换,我试图理解这条线的解释方式.
我已经隔离了每个角色
(![]+[])[+[]] 版画 "f"(![]+[])[+!+[]] 版画 "a"([![]]+[][[]])[+!+[]+[+[]]] 版画 "i"(![]+[])[!+[]+!+[]] 版画 "l"我还设法打破了每个字母除外的表达式 "i"
"f"![]空数组是一个对象,它根据ECMAScript的文档,点9.2的计算结果为true当转换为一个boolean,所以这是false
false+[]根据Point 11.6.1,二元+运算符的两个参数都转换为String,因此我们得到"false"+"",它进行求值"false"
+[]如果参数是a,则一元加号运算符会导致ToNumber转换,然后ToPrimitive转换Object.通过调用[[DefaultValue]]对象的内部方法来确定这种转换的结果.如果是空数组,则默认为0.(ECMAScript的文档,章节:11.4.6,9.3,9.1)
"false"[0]我们正在访问索引处的字符0,因此"f"
"a"同样的故事,这里唯一的区别是方括号中的部分中的额外转换(其计算为指向字符串中另一个字符的数字"false"),由使用一元+和!运算符触发.
+[]0 …
考虑以下示例代码(也许我做错了?)
var FlareCurrency = {
};
export {FlareCurrency};
Run Code Online (Sandbox Code Playgroud)
我有以下任务:
gulp.task("compile:add-new-currency-minified", function(){
return gulp.src('src/add-new-currency/**/*.js')
.pipe(babel())
.pipe(concat('Flare-AddNewCurrency.js'))
.pipe(uglify({"preserveComments": "all"}))
.pipe(gulp.dest('dist/minified/'));
});
Run Code Online (Sandbox Code Playgroud)
当我运行这个时,我得到以下内容:
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var FlareCurrency={};exports.FlareCurrency=FlareCurrency;
Run Code Online (Sandbox Code Playgroud)
为了它的乐趣,我想在控制台中运行它,是的我知道它什么都不做,但我没想到会看到这个:
Uncaught ReferenceError: exports is not defined(…)
Run Code Online (Sandbox Code Playgroud)
非缩小版:
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var FlareCurrency = {};
exports.FlareCurrency = FlareCurrency;
Run Code Online (Sandbox Code Playgroud)
抛出同样的错误.想法?
JavaScript并不关心你的字符串是双引号"double"还是单引号'single'.
ECMAScript 5的严格模式的每个示例都"use strict"使用双引号启用它.我可以执行以下操作(单引号):
alert(function(){
'use strict';
return !this;
}());
Run Code Online (Sandbox Code Playgroud)
如果启用了Strict模式,则返回true,否则返回false.
ECMAScript第五版(2009年12月发布)介绍了一系列新方法(详见此表).但是,仍然存在那些没有实现这些新方法的旧浏览器.
幸运的是,存在一个方便的脚本(用JavaScript编写) - ES5-shim - 它在不存在的环境中手动实现这些方法.
但是,我不确定如何提供ES5-shim ...我应该只是"给"所有浏览器,如下所示:
<script src="es5-shim.js"></scipt>
Run Code Online (Sandbox Code Playgroud)
或者我应该包括一个检查,以便"打扰"那些真正需要它的浏览器,如下所示:
<script>
if ( !Function.prototype.hasOwnProperty( 'bind' ) ) {
(function () {
var shim = document.createElement( 'script' );
shim.src = 'es5-shim.js';
var script = document.getElementsByTagName( 'script' )[0];
script.parentNode.insertBefore( shim, script );
}());
}
</script>
Run Code Online (Sandbox Code Playgroud)
(我Function.prototype.bind用来检查浏览器是否实现了所有新的ECMAScript 5方法.根据我上面链接的兼容性表,bind它是实现ECMAScript 5方法的"最后堡垒".)
当然,为了使这个垫片有效,它必须在所有其他脚本之前执行,这意味着我们希望在页面的早期包含上述SCRIPT元素(在HEAD中,在所有其他SCRIPT元素之前).
那么,第二个例子是否是向浏览器提供ECMAScript 5-shim的好方法?有没有更好的方法呢?
ECMAScript 5 array.forEach(callback[, thisArg])在迭代数组上非常方便,并且具有许多优于语法的优点:
有没有理由不object.forEach替换for(var key in object)?
当然,我们可以使用JavaScript实现,如_.each或$ .each,但这些都是性能杀手.
我正在尝试运行此代码,但它给了我以下错误:
Animal.ts(10,13):错误TS1056:访问者仅在定位ECMAScript 5及更高版本时可用.Animal.ts(14,13):错误TS1056:访问者仅在定位ECMAScript 5及更高版本时可用.
interface IAnimal{
name : string;
sayName():string;
}
class AnimalImpm implements IAnimal{
private _name : string = '[Animal]';
get name():string{
return this._name;
}
set name(name:string){
this._name = name;
}
constructor(name:string){
this.name = name;
}
sayName():string {
console.log(`My name is ${this.name}`);
return "Hello";
}
}
Run Code Online (Sandbox Code Playgroud) ecmascript-5 ×10
javascript ×10
ecma262 ×2
strict ×2
accessor ×1
arrays ×1
babeljs ×1
browser ×1
coffeescript ×1
comparison ×1
ecmascript-6 ×1
es5-shim ×1
foreach ×1
function ×1
gulp ×1
html ×1
obfuscation ×1
oop ×1
scope ×1
types ×1
typescript ×1