// 小栗子 function fn(a) { console.log(a); var a = 123; console.log(a); function a() {} console.log(a); console.log(b); var b = function() {}; console.log(b); function d() {} console.log(d)}fn(1);输出 function(){} 123 123 undefined function() {} function d(){}
-
预编译(全局的预编译) -
生成GO对象(Global Object) -
变量声明的变量名作为GO的属性名,值赋予undefined
3.找函数声明,值赋予函数体 // 小栗子 console.log(test); function test(test) { console.log(test); var test = 123; console.log(test); function test() {} } test(1)
// 输出 function test(test){} fucntion test() {} 123 // 稍微有点难的哦 global = 100; function fn() { console.log(global); 此时找到fn函数内有变量声明 global undefined global = 200; console.log(global); var global = 300; } fn(); var global;
输出 undefined 200 因为AO中有global
19.闭包 现象 当内容函数被保存到外部时,将会产生闭包,导致原有作用域链不释放,造成内存泄露。 // 小栗子 fucntion test() {} () —> 不会被执行,因为test是函数声明不是函数表达式 123; 234; 123, 234 ----> 可以叫做表达式 var test = function() {console.log(‘a’)} () ----> 能执行 输出a
被执行函数执行的表达式就成了立即执行函数,并忽略函数名引用
// 小栗子 var test = function() { console.log(‘a’) }; 执行 test() test --> 输出为function
当写成 var test = fucntion() {console.log(‘a’)} () 执行完之后 test —> undefined 立即执行函数的几个题
// 给ui下的四个li绑定一个事件,输出每个li的位置 function test() { var liCollection = document.getElementsByTagName(‘li’); var len = liCollection.length; for(var i = 0; i < len; i ++) { (function(j) { liCollection[j].onclick = function() { console.log(j + 1) } }(i)) } } // 如果没有立即执行函数,每个li输出的i都是li标签的数量,因为当li被点击的时候,li函数的GO作用域中的i已经变成了len
// 求一个字符串的字节长度(提示:字节串有一个方法,charCodeAt();一个中文占两个字节,一个英文占一个字节) charCodeAt返回指定位置的字符串的Unicode编码,这个返回值是0~65535之间的整数。(当返回值<= 255时为英文,>时就是中文)
function retByteSlean(target) { if(typeof(target) !== “string”) { return; } var len = target.length, count = len; for(var i = 0; i < len; i++) { if(target[i].charCodeAt() > 255) { count++; } } return count; }
23.包装类(原始值有对象方式的创建方式) 在JavaScript中数字有两种个数字,字符串分两种字符串,布尔值分为两种布尔值,原始值数字才是原始值,原始值字符串才是原始值,这里还有非原始值数字和非原始值字符串,new Number(xxx) 默认是Number {0} 、new String(xxx)默认是 String {""}、 new Boolean() 默认是Boolean {false}
注意:undefined和null没有包装类 // 包装类有自己的属性和方法 var num = new Number(123); num.abc = “ac”; console.log(num.abc); // 输出 “ac” num.fn = function() { console.log(123) }; num.fn() // 输出 123
// 但是原始值本身没有属性和方法,也不能加属性和方法,也不能访问属性和方法 var num = 3; num.length = 4;// 原始值num是没有length属性的,它会转换为new Number(3).length = 4,执行完这段代码之后Number销毁 console.log(num.length); // 此时又重新转换为new Number(3),此时输出length为undefined。
包装类面试题 // 面试题 var str = “abc”; str += 1; var test = typeof(str); if(test.length === 6) { test.sign = “typeof返回的值可能是string”; // 转换为包装类之后销毁 } console.log(test.sign) // 再次转换为包装类 因为new String(“test”)没有sign这个属性,输出为undefined 原始值没有方法和属性 // 输出为undefined
24.原型 定义:原型是function对象的一个属性,它定了构造函数制造出来的对象的公共祖先,通过构造函数生产的对象可以继承该原型的属性和方法,原型也是对象。
原型的特点: 我们创建出来的对象,都会继承了父级的prototype,他不仅有自己定义的属性,还有“他爹”(原型上)的属性,当我们构造出来的对象有公共的不改变的属性,我们可以把这些不变的属性到原型上面 // 小栗子 function Car(color, ower) { this.color = color; this.ower = ower; this.height = 1400; this.weight = 4900; } var car = new Car(“red”, “lei.zhou”);
// 每次new Car()都会走一遍 this.height this.weight, 而这两个属性是不变的,可以直接放到Car的原型上面 Car.prototype = { height: 1400, weight: 4900} 原型的增删改查(构造函数的原型本职上是对象,它的增删改查就是对象的增删改查) // 小栗子 Person.prototype.lastName = “lei”; function Person (name) { this.name = name; } var person = new Person(“张”);
// 原型的增 Person.prototype.firstName= “zhou”; // 原型的删 delete Person.prototype.firstName; 返回true // 原型的改 Person.prototype.lastName = “leizi”; // 原型的查 Person.prototype.firstName; 删除 “zhou”
原型的写法 // 原型的两种写法 第一种 XX.prototype.xx = xx Person.prototype.name = ‘buhaoba’; 第二种 XX.prototype = {xx: xx} Person.prototype = { name: “buhaoba”}; 原型的constructor(构造器) // 查看对象的构造函数 function Car() {} var car = new Car(); console.log(car.constructor); // 输出为 function Car(){}
// car.constructor有时候也会找错生产自己的工厂 function Person() {} car.prototype = { constructor: Person } function Car() {} var car = new Car(); console.log(car.constructor); // 输出为Person 原型的__proto__ Person.prototype.lastName = “abc”; function Person() {} var person = new Person(); console.log(person);
从上图可以知道输出person.name时会沿着__proto__找到Person.prototype,proto__跟Person.prototype指向同一个地址,他两都是引用值,在原型中找对应的属性,Person.prototype属性有lastName和constructor,constructor这个指向function Person() {},Person.prototype也有自己的__proto,这个__proto__指向Object.prototype
修改原型对构造出来对象的影响 Person.prototype.name = “sunny”; function Person() {} var person1 = new Person(); Person.prototype = {name: ‘abc’}; console.log(person1.name); // 输出为"sunny" var person2 = new Person(); console.log(person2.name); // 输出为"abc"
Person.prototype.name = “sunny”; function Person() {} var person = new Person(); Person.prototype.name = ‘abc’; console.log(person.name); // 输出为"abc" 为啥会出现以上这种情况呢,原因竟然是:
第一种:打印person1.name 沿着__proto__找Person.prototype,此时的Person.prototype的指向为stack0001,这里面的name为“sunny”,所以输出“sunny”;打印person2.name 沿着__proto__找Person.prototype,Person.prototype重新赋值一个对象,指向发生了改变,此时的Person.prototype的指向为stack0002,这里面的name为“abc”,所以输出“abc”。
第二种:打印person.name 沿着__proto__找Person.prototype,此时的Person.prototype的指向为stack0001,这里面的name从“sunny”变成了“abc”,指向还是之前的 stack0001,只是内容改变了,所以输出“abc”。
25.原型链 如何构成原型链呢? Grand.prototype.lastName = “lei”; function Grand() { this.age = 1000; } var grand = new Grand(); Father.prototype = grand; function Father() { this.height = 123; } var father = new Father(); Son.prototype = father; function Son() { this.weight = “henqin”; } var son = new Son(); console.log(son); 原型链属性的增删改查 // 原型链的增 构造函数名.prototype.xx = xx; Father.prototype.happyState = true; console.log(son.happyState); 输出为true // 原型链的删 delete 构造函数名.prototype.xx delete Father.prototype.happyState; console.log(son.happyState); 输出为undefined // 原型链的改 (改值的时候不要直接等于一个引用值,这样会让原型链断裂) 构造函数名.prototype.原有属性名= xx; Father.prototype.age = 15; console.log(son.age ); 输出为15 // 原型链的查 从儿子级一直到祖先查,如果祖先有和自己一样的属性,输出自己的 绝大多数对象最终都会继承自Object.prototype // 小栗子 function Person() {} var person = new Person; person.toString(); 输出 “[object Object]” 输出是因为Person的__proto__指向Object.prototyepe,Object.prototyepe里有toString这个属性 Object.create(原型) 构造对象 绝大多数对象最终都会继承自Object.prototype,为什么说绝大多数呢?看以下内容就可明白 var obj = Object.create(“原型 可以自己指定”); var prop = { name: 123 } var obj1 = Object.create(prop); console.log(obj1); 如果create里面传值为null时,他就不继承自Object.prototype var obj = Object.create(“原型 可以自己指定”); var prop = null; var obj1 = Object.create(prop); console.log(obj1);
重写系统定义函数定义的原型上的方法 var num = 123; num.toString(); 输出为“123” 为啥会输出字符串123呢,因为Number.prototype原型上面有 toString = function() {} Number.prototype中没有的属性才会找Object.prototype上的属性
// 包装类(Number String Boolean) 和 Array Object都有自己的toString方法 调用的方法不同,输出的结果也不同
Object.prototype.toString.call(123) 输出 “[object Number]”
转自:https://blog.csdn.net/qq_40860137/article/details/108330340?utm_source=app&app_version=4.19.1&code=app_1562916241&uLinkId=usr1mkqgl919blen
|