你不知道的JavaScript小记

mac2024-07-19  58

你不知道的JavaScript小记

函数作用域和块作用域的区别之一 块作用域: 当使用 var 声明变量时,它写在哪里都是一样的,因为它们最终都会属于外部作用域。 如:我们在 for 循环的头部直接定义了变量 i,通常是因为只想在 for 循环内部的上下文中使用 i,而忽略了 i 会被绑定在外部作用域(函数或全局)中的事实,可以使用let劫持块作用域,使用 let 进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不 “存在”。 for (var i = 0; i<4; i++) { console.log(i); } console.log(i); // 4 函数作用域: 在任意代码片段外部添加包装函数,可以将内部的变量和函数定义“隐藏”起来,外部作用域无法访问包装函数内部的任何内容。 例如: var a = 2; function foo() { // <-- 添加这一行 var a = 3; console.log( a ); // 3 } // <-- 以及这一行 foo(); // <-- 以及这一行 console.log( a ); // 2

立即执行函数 var a = 2; (function foo() { var a = 3; console.log( a ); // 3 })(); console.log( a ); // 2 由于函数被包含在一对 ( ) 括号内部,因此成为了一个表达式,通过在末尾加上另外一个( ) 可以立即执行这个函数,比如 (function foo(){ … })()。第一个 ( ) 将函数变成表达式,第二个 ( ) 执行了这个函数。这种模式很常见,几年前社区给它规定了一个术语:IIFE,代表立即执行函数表达式(Immediately Invoked Function Expression);

this 调用位置 每个函数的 this 是在调用时被绑定的,完全取决于函数的调用位置,调用位置就是函数在代码中被调用的位置(而不是声明的位置) 绑定规则 (1)默认绑定: function foo() { console.log( this.a ); } var a = 2; foo(); // 2 声明在全局作用域中的变量(比如 var a = 2)就是全局对象的一个同名属性,this 指向全局对象。 (2)隐式绑定: function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; obj.foo(); // 2 当 foo() 被调用时,它的落脚点确实指向 obj 对象。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的 this 绑定到这个上下文对象。因为调用 foo() 时 this 被绑定到 obj,因此 this.a 和obj.a 是一样的。 (3)显示绑定: function foo() { console.log( this.a ); } var obj = { a:2 }; foo.call( obj ); // 2 通过 foo.call(…),调用 foo 时强制把它的 this 绑定到 obj 上。 new绑定: function foo(a) { this.a = a; } var bar = new foo(2); console.log( bar.a ); // 2 使用 new 来调用 foo(…) 时,我们会构造一个新对象并把它绑定到 foo(…) 调用中的 this上。new 是最后一种可以影响函数调用时 this 绑定行为的方法,我们称之为 new 绑定。

箭头函数的this function foo() { // 返回一个箭头函数 return (a) => { //this 继承自 foo() console.log( this.a ); }; } var obj1 = { a:2 }; var obj2 = { a:3 }; var bar = foo.call( obj1 ); bar.call( obj2 ); // 2, 不是 3 ! foo() 内部创建的箭头函数会捕获调用时 foo() 的 this。由于 foo() 的 this 绑定到 obj1,bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的绑定无法被修改。(new 也不行!)

JavaScript类型:6种 • string • number • boolean • null • undefined • object 注 1:原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判 断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”

内置对象 JavaScript 中只有对象。 JavaScript 中还有一些对象子类型: • String • Number • Boolean • Object • Function • Array • Date • RegExp • Error 但是在 JavaScript 中,它们实际上只是一些内置函数。这些内置函数可以当作构造函数来使用,如: var strPrimitive = “I am a string”; typeof strPrimitive; // “string” strPrimitive instanceof String; // false var strObject = new String( “I am a string” ); typeof strObject; // “object” strObject instanceof String; // true // 检查 sub-type 对象 Object.prototype.toString.call( strObject ); // [object String]

可计算属性名 ES6 增加了可计算属性名,可以在文字形式中使用 [] 包裹一个表达式来当作属性名: var prefix = “foo”; var myObject = { [prefix + “bar”]:“hello”, [prefix + “baz”]: “world” }; myObject[“foobar”]; // hello myObject[“foobaz”]; // world

遍历 for…in 循环可以用来遍历对象的可枚举属性列表,使用 for…in 遍历对象是无法直接获取属性值的,因为它实际上遍历的是对象中的所有可枚举属性,你需要手动获取属性值。那么如何直接遍历值而不是数组下标呢?ES6 增加了一种用来遍历数组的 for…of 循环语法。

JavaScript中的函数不是构造函数 new 会劫持所有普通函数并用构造对象的形式来调用它 如: function NothingSpecial() { console.log( “Don’t mind me!” ); } var a = new NothingSpecial(); // “Don’t mind me!” a; // {},上面的new不过是调用NothingSpecial函数,并非创建新的函数

NothingSpecial 只是一个普通的函数,但是使用 new 调用时,它就会构造一个对象并赋值给 a,这看起来像是 new 的一个副作用(无论如何都会构造一个对象)。这个调用是一个构造函数调用,但是 NothingSpecial 本身并不是一个构造函数,换句话说,在 JavaScript 中对于“构造函数”最准确的解释是,所有带 new 的函数调用。函数不是构造函数,但是当且仅当使用 new 时,函数调用会变成“构造函数调用”。

最新回复(0)