你不知道的js(代码片段)

DaiHanlong DaiHanlong     2022-11-23     752

关键词:

作用域 LHS RHS 区别

  1. 如果 RHS 查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError 异常。值得注意的是,ReferenceError 是非常重要的异常类型。
    相较之下,当引擎执行 LHS 查询时,如果在顶层(全局作用域)中也无法找到目标变量,
    全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非 “严格模式”下。

  2. ReferenceError 同作用域判别失败相关,而 TypeError 则代表作用域判别成功了,但是对 结果的操作是非法或不合理的。

  3. 在严格模式的程序中,eval(..) 在运行时有其自己的词法作用域,意味着其 中的声明无法修改所在的作用域

  4. 使用 let 进行的声明不会在块作用域中进行提升
    变量和函数声明从它们在代码中出现的位置被“移动”到了最上面。这个过程就叫作提升。
    只有声明本身会被提升,而赋值或其他运行逻辑会留在原地.并且函数会优先提升.

5.词法作用域和动态作用域的区别. 好在 javascript并不具有动态作用域.
主要区别:词法作用域是在写代码或者说定义时确定的,而动态作用域是在运行时确定的。
词法作用域关注函数在何处声明,而动态作用域关注函数从何处调用。

this和对象原型

this的绑定规则

  1. 默认绑定.
    独立调用函数时,会默认绑定到全局对象. 严格模式下,全局对象无法使用默认绑定,因此this会绑定到undefined
    注意: nodejs环境下的this指向的是 module.exports,默认为
    但是函数中默认的this,指向的是 global 对象.

  2. 隐式绑定
    函数调用的位置有上下文对象,this会绑定到这个上下文对象.
    主要注意的是要小心隐式丢失.

  3. 显式绑定
    call apply 方法
    bind 方法

  4. new 绑定

优先级是 4 > 3 > 2 > 1

javsscript里面的类型

  1. js有7种内置类型
    string number boolean undefined object null symbol

typeof ‘aaa‘ // string
typeof 3 // number
typeof true // boolean
typeof undefined //undefined

let a = ;
typeof a // object

注意:
typeof null // object

let func = function()
typeof func // function

  1. 内置对象
    String Number Boolean Object Function Array Date RegExp Error
    其实只是一些内置函数.

注意基本类型和这些内置对象的区别,如:
let str = ‘I am a string‘; // 又叫字符串字面量
typeof str; // string
str instanceof String; // false

let str2 = new String(‘I am a string‘);
typeof str2; // object
str2 instanceof String; // true

检查上面这些内置对象的方法:
Object.prototype.toString.call(str2); // [object String]

如下代码会自动把字面量转换成String对象,所以可以访问属性和方法.
let str = ‘I am a string‘;
console.log(str.length);
console.log(str.charAt(3)); // ‘m‘

string 对应的构造形式 String
number 对应的构造形式 Number
boolean 对应的构造形式 Boolean

null 和 undefined 没有对应的构造形式.

  1. 属性
    在对象中,属性名永远都是字符串。如果你使用 string(字面量)以外的其他值作为属性 名,那它首先会被转换为一个字符串。即使是数字也不例外,虽然在数组下标中使用的的 确是数字,但是在对象属性名中数字会被转换成字符串,所以当心不要搞混对象和数组中 数字的用法.

es6添加了可计算属性名,可以在文字形式中使用[]包裹一个表达式来当作属性名.

var prefix = "foo";
var myObject = 
    [prefix + "bar"]:"hello", 
    [prefix + "baz"]: "world"
;
myObject["foobar"]; // hello
myObject["foobaz"]; // world

Object.assign 只会进行浅拷贝.

  1. 属性描述符
var myObject = 
    a:2
;
let pd = Object.getOwnPropertyDescriptor( myObject, "a" );
// pd:
// 
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true 
// 

使用 Object.defineProperty(..)来添加一个新的属性或者修改一个已有的属性.

a. writable
如果设置成 false,则不能修改值了.

b. configurable
如何 configurable 为false, 则后面就不能将这个属性的 configurable 设置成true了,
并且这个属性也不能被删除. 但是可以被修改.
同时, 只能将 writable 的状态从 true改成false,不能由 false 改成 true.

c. enumerable
设置成false,则不会出现在for..in循环中. 但是还是可以正常访问.
propertyIsEnumerable 这个方法可以判断属性名是否可枚举,并且不会检查原型链

  1. 属性不变性

a. 将属性的 writabel 和 configurable 都设置成false即可.
那么这个属性就不可被修改和重定义或者删除.

b. 禁止扩展
Object.preventExtensions(..); 只是不能添加新的属性,但是可以修改属性的值,
还可以删除属性.

c. 密封
Object.seal(..), 这个方法会调用Object.preventExtensions,然后将现有属性的configurable设置成false.
但是可以修改属性的值,不能删除属性.

d.冻结
Object.freeze(..),
这个方法实际会调用Object.seal(),并且把所有的属性的writable设置成false, 这是最高级别的不变性.

  1. [[Get]]/[[Put]]
    set get的定义.

  2. 存在性
var myObject =  
    a:2
;
 ("a" in myObject); // true
 ("b" in myObject); // false
 myObject.hasOwnProperty( "a" ); // true
 myObject.hasOwnProperty( "b" ); // false

in 操作符会检查属性是否在对象及其原型链中(不管枚举属性是否为true,都会判断).
hasOwnProperty 则不会检查原型链.

Object.keys(..) 会返回一个数组,包含所有可枚举属性,
Object.getOwnPropertyNames(..) 会返回一个数组,包含所有属性,无论它们是否可枚举。

in 和 hasOwnProperty(..) 的区别在于是否查找 [[Prototype]] 链,
然而,Object.keys(..) 和 Object.getOwnPropertyNames(..) 都只会查找对象直接包含的属性。

8.遍历
for..in 用来遍历对象的可枚举属性(包含原型链,要求枚举属性必须为true,注意和 in 操作符的区别).
但是如果要遍历值,则使用 foreach every some 等.

es6 的 for..of 可以用来遍历数组的值.
for..of 还可以用来遍历实现了 iterator 的对象.

混合对象"类"

  1. 显示混入
function mixin(sourceObj,targetObj)
    for(let k in sourceObj)
        if(!(k in targetObj))
            targetObj[k] = sourceObj[k];
        
    
    return targetObj;
;

这种是浅复制,如果有数组或者对象或者函数(函数也是对象),则会同时影响sourceObj和targetObj.

  1. 寄生继承

  2. 隐式混入

  3. 原型链 属性屏蔽
let another =  a : 2;
let myobj =  Object.create(another);

console.log(myobj); // 
console.log(myobj.hasOwnProperty("a"));  // false
myobj.a = 5;   
console.log(myobj.hasOwnProperty("a")); // true
console.log(myobj);  a:5

属性屏蔽规则:
如:myobj.a = 5;
a.如果myobj包含a属性,则不管原型链上是否有a属性, 都会直接应用到myobj对象上,而不会影响原型链上的a.

b.如果myobj本身不包含a属性,则会遍历原型链,如果原型链上也没有a属性,则a会被添加到myobj对象上.

c.如果myobj本身不包含a属性,但是原型链上有a属性,并且a属性的 writable为true,则会直接添加到myobj对象上,但是不会影响原型链上的a(属性屏蔽),如果原型链上的a属性的writable为false,非严格模式下不会产生效果,严格模式下报错.

d.如果myobj本身不包含a属性,但是原型链上a是一个setter,则会调用这个setter,而a属性不会被添加myobj上.

总结: 如果要给myobj添加a的属性去屏蔽原型链上的属性a, 则使用Object.defineProperty(..)
注意 隐式屏蔽. 如:
myobj.a++,相当于 myobj.a = myobj.a + 1;

function Foo()
let foo = new Foo();

使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  1. 创建(或者说构造)一个全新的对象。
  2. 这个新对象会被执行[[原型]]连接。
  3. 这个新对象会绑定到函数调用的this。
  4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

《你不知道的js》提升(代码片段)

四、提升:一)、声明与赋值:? 在JS引擎中,我们一般认为的变量或函数声明,实际上分为两个部分。声明赋值//变量提升a=2;vara;console.log(a);//函数提升foo();functionfoo() console.log(1);? vara=2;? 这句声明实际上会被看为vara;a=2;两个部分... 查看详情

你不知道的js来聊聊this(代码片段)

为什么要使用this?什么是this?来看一段代码functionidentify()returnthis.name.toUpperCase();functionspeak()vargreeting="Hello,I‘m"+identify.call(this);console.log(greeting);varme=name:"Kyle";varyou=name:"Reader" 查看详情

你不知道的js(代码片段)

作用域LHSRHS区别如果RHS查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出ReferenceError异常。值得注意的是,ReferenceError是非常重要的异常类型。相较之下,当引擎执行LHS查询时,如果在顶层(全局作用域)中也无法找到目标... 查看详情

《你不知道的js(中卷)》关于this(代码片段)

一、关于this:一)、为什么要用this?functionidentity() returnthis.name.toUpperCase();varme= name:"Kyle";varyou= name:"Reader";identity.call(me);//Kyleidentity.call(you);//Reader? 观察上面的代码,使 查看详情

你不知道的js(代码片段)

1、作用域 块级作用域let只在函数内部自己的作用域内有效 全局作用域var 函数作用域 找不到作用域抛出ReferenceError变量有了则抛出TypeError 先声明后赋值 函数提升变量提升函数优先,函数声明提升在普通变量之前 函数表达... 查看详情

你不知道的js系列上(45)-隐式混入(代码片段)

varSomething=  cool:function()    this.greeting=‘HelloWorld‘;    this.count=this.count?this.count+1:1;  Something.cool();Something.greeting;//‘HelloWorld‘Something.count;//1varAnother=  cool:func 查看详情

《你不知道的js》——this全面解析(代码片段)

默认绑定//全局对象用于默认绑定functionfoo()console.log(this.a)vara=2;foo();//2//严格模式下,不能将全局对象用于默认绑定functionfoo()‘usestrict‘;console.log(this.a)vara=2;foo();//TypeError:thisisundefined//在严格模式下调用foo()则不影响默认绑定func 查看详情

你不知道的js系列(39)-对象遍历(代码片段)

for循环可以遍历数组varmyArray=[1,2,3];for(vari=0;i<myArray.length;i++)  console.log(myArray[i])//123ES5增加了数组的辅助迭代器,包括forEach(...)、every(...)、some(...)forEach(...)会遍历数组中的所有值并忽略回调函数的返回值every(...)会一直运行直... 查看详情

《你不知道的js(上卷)》作用域闭包(代码片段)

五、作用域闭包:? 闭包不是神奇的魔法,它只是遵循我们前几章一直介绍的词法作用域书写代码的自然结果。? 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。一... 查看详情

《你不知道的js(中卷)》行为委托(代码片段)

六、行为委托:? 总结第五章,JS中的[[Prototype]]机制就是对象之间的关联关系。一)、面向委托的设计:? 想要学习更直观的使用[[Prototype]],必须认识到它代表了一种不同于类的设计模式。1、类理论:? 类设计模式鼓励你在继承时... 查看详情

《你不知道的js(中卷①)》语法(代码片段)

五、语法:? 语法(grammar)与词法(syntax)不同。后者强调语言的运算符、关键字等。而语法定义了此法规则是如何构成可运行的程序代码的。一)、语句和表达式:语句(statement)与表达式(expression),举例说明:vara=3*6;a=3*6... 查看详情

你不知道的js系列上(45)-显式混入(代码片段)

JS的对象机制并不会自动执行复制行为,由于其他语言中表现出来的复制行为,因此JS开发者也想出了一个方式来模拟类的复制行为,这个方法就是混入。我们先看第一种,显式混入。//非常简单的mixin()例子functionmixin(sourceObj,targe... 查看详情

你不知道的js系列(13)-什么是闭包(代码片段)

当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行functionfoo()  vara=2;  functionbar()    console.log(a);    returnbarvarbaz=foo();baz();//2——朋友,这就是闭包的效果在foo... 查看详情

你不知道的js系列(14)-闭包无处不在(代码片段)

上一节的闭包是为了解释如何使用闭包而人为地在结构上进行修饰,在昨天的闭包基础上,我们可以更加灵活的使用闭包functionwait(message)  setTimeout(functiontimer()    console.log(message)  ,1000)wait(‘hello,consure‘);内部函数timer... 查看详情

你不知道的js系列(29)-对象属性(代码片段)

存储在对象容器内部的是这些属性的名称,它们就像指针(从技术角度来说是引用)一样,指向这些值真正的存储位置。 varmyObject=  a:2myObject.a;//2myObject[‘a‘];//2.语法通常被称为‘属性访问’,[]语法通常被称为&lsqu... 查看详情

《你不知道的js(中卷)》混合对象“类”(代码片段)

四、混合对象“类”:? 在研究类的具体机制之前,首先介绍面向类的设计模式:实例化(instantiation)、继承(inheritance)和(相对)多态(polymorphism)。一)、类理论:? 面向对象编程强调的是数据和操作数据的行为本质上是... 查看详情

你不知道的js系列(12)-声明提升(代码片段)

我们直觉上会认为JavaScript代码在执行时是由上到下一行一行执行的。但实际这并不完全正确 a=2;vara;console.log(a);这里可能会认为是undefined,因为vara声明在a=2之后。实际输出了2。 console.log(a);vara=2;鉴于上面的代码可能会是2... 查看详情

你不知道的js系列(22)-thisnew绑定(代码片段)

在传统的面向类的语言中,“构造函数“是类中的一些特殊方法,使用new初始化类时会调用类中的构造函数。通常的形式是这样的something=newMyClass(..);然而JavaScript中new的机制实际上和面向类的语言不同。它们只是被new操作... 查看详情