1. 函数实例化原理
1.1 构造函数中的this
- this指向的不是构造函数本身
- 当构造函数实例化的时候,AO生成 就已经生成了this
- new实例化了对象之后,this指向的是这个实例化的对象,在没有实例化之前,指向的window ```javascript // 在没有实例化之前,指向的是window,new实例化之后,this指向的是这个实例化的对象 function Car(color, brand){ this.color = color; this.brand = brand; console.log(this); }
Car(); var c1 = new Car(‘red’, ‘mazda’); // 第一次输出 window // 第二次输出 Car{}
// 上述实例化理解 function Car(color, brand){ this.color = color; this.brand = brand; // var this ={ // color: color, // brand: brand, // } // 隐式增加了return this }
// 不用new 直接指向函数 function Car(color, brand){ var obj = {} obj.color = color; obj.brand = brand;
return obj }
var car = Car(‘red’, ‘audi’); console.log(car);
<a name="eLJoq"></a>## 1.2 构造函数中的return- number, string, undefined, boolean, null等原始值,会被忽略,结果还是return this- [], {}, function(){},等引用值,会改变返回引用值```javascriptfunction Car(){return null // undefined, string boolean, number}var car = new Car();console.log(car); // Car {}function Car(color){this.color = color;return [] // {} function(){}}var car = new Car();console.log(car); // [], {}, function(){}console.log(car.color); // undefined
2. 包装类
2.1 new Number 转换为数字对象
var a = 1;console.log(a); // 1 原始值var b = new Number(a);// 数子对象 => 实例化对象后的数字console.log(b); // Number{1}b.len = 1;b.add = function(){console.log(1);}console.log(b);// Number {1, len: 1, add: f()}var d = b + 1;console.log(d);// 2 此时的运算使得b又变成了一个原始值console.log(b);// Number {1, len: 1, add: f()} 参与运算之后,又成了数字对象
2.2 new string 转换为字符串对象
var a = 'abc';console.log(a); // abcvar aa = new String('abc');aa.name = 'aa';console.log(aa);// {'abc', name:'abc'}var bb = aa + 'bcd';console.log(bb);// 'abcbcd'console.log(aa); // {'abc', name:'abc'}
2.3 JS包装类过程
2.3.1 原始值并没有自己的属性和方法
给原始值添加属性和方法, 系统会包装类进行添加, 但是没有提供变量用于保存, 系统会默认delete
// 原始值并没有自己方法和属性var a = 123;a.len = 3;// a是原始值,不能添加属性// new Number(a).len = 3;// delete new Number()cosnole.log(a.len);
var str = 'abc';// new String(str).length -> str经过了包装类console.log(str.length);// 3
2.3.2 数组截断
数组可以被length 进行截断
// 数组的截断var arr = [1, 3, 4, 5, 6];arr.length = 3;console.log(arr); // [1, 3 ,4]arr.length = 6;// arr -> [1, 3, 4, 5, 6, empty]// arr[6] => undefined// 字符串的截断?var str = 'abc';str.length = 1;// new String(str).length = 1 -> deleteconsole.log(str);// abc// 再次new String(str).lengthconcole.log(str.length);// 3
3.案例
案例1
var name1 = 'languiji';name1 += 10; // name1 => 'languiji10'var type = typeof(name1);// 'string'if(type.length === 6){type.text = 'string';// new String(type).text = 'string'// delete}console.log(type.text); // undefined
案例2
function Test(a, b, c){var d = 1;this.a = a;this.b = b;this.c = c;function f(){d++;console.log(d);}this.g = f;}var t1 = new Test();t1.g(); // 2t1.g(); // 3var t2 = new Test();t2.g(); // 2
案例3
var x = 1,y = z = 0;function add(n){return n = n + 1;}y = add(x);function add(n){return n = n + 3;}z = add(x);console.log(x, y, z); // 1 4 4
案例4
// 函数1function foo1(){console.log(arguments);return x;}foo1(1, 2, 3, 4, 5);// 函数2function foo2(x){console.log(arguments);return x}(1, 2, 3, 4 ,5)// 函数3(function foo3(x){console.log(arguments);return x})(1, 2, 3, 4, 5)以上那个函数可以输出 1, 2, 3, 4, 51.3可以2 => (1, 2, 3, 4, 5)被当做表达式,不会被执行
案例5
// 当非严格模式下中的函数没有包含 *剩余参数,默认参数,解构赋值,那么arguments对象中的值会跟踪参数的值function b(x, y, a){// a = 10;// console.log(arguments[2]); // 10arguments[2] = 10;console.log(a); // 10}b(1, 2, 3);严格模式下不会跟踪参数的值'use strict'function b(x, y, a){arguments[2] = 10;console.log(a); // 3}b(1, 2, 3);
4.练习
写一个函数,接受任意一个字符串,算出这个字符串的总字节数
// ASCII 码 表1 0- 127, 表2 128-255// 一个字节// UNICODE码 -> 涵盖ASCII码 2个字节function bytes(str){var allBytes = 0;for(var i = 0; i < str.length; i++){var code = str.charCodeAt(i);if(code <= 256){allBytes += 1;}else{allBytes += 2;}}console.log(allBytes);}bytes('你好,中国! hello!');function getBytes(str){var Bytes = str.length;for(var i = 0; i < str.length; i++){var codeIndex = str.charCodeAt(i);if(codeIndex > 255){Bytes++;}}return Bytes;}
