// 这里定义一个构造函数 Foo
function Foo() {
// 这里没有let var const 声明直接赋值,相当于全局变量(window)但是这个函数没有执行,里面赋值就不会进行
// 注意这个方法,不会添加的 new出来的实例化对象上面
getName = function () {
console.log(1);
};
// 这里返回 this 是为了后面 Foo().getName(); 进行调用 函数没有返回值就是 udf udf点任何属性都会报错的
// 这个也可以不返回 Foo() getName() 这样也是可以的
return this;
}
Foo.getName = function () {
// 函数是一个特殊的对象 ,只不过函数多了一个 call 属性可以进行调用而已 call也可以用来修改this指向
// 也就是说 Foo这个对象 上面添加一个方法 这个方法不在 构造函数里面 那么 new出来的对象也不会用这个方法
// 这就是静态成员 ,es6的类可以用 static关键字 变成静态成员
// 静态成员相对应的是 动态成员 也就是new可以继承的
console.log(2);
};
Foo.prototype.getName = function () {
// 这个是添加到原型连上面的 new Foo出来的对象 就可以调用这个方法 相当于 Foo.prototype.getName() 这样调用;
// es6 就可以不用怎么麻烦在原型上添加方法
// class Foo {
// 这个方法相当于添加到原型上面了
// getName = function () {
// console.log(3);
// };
// }
console.log(3);
};
var getName = function () {
// 这是声明全局的变量 ,通过var 声明的 var会变量提升,这里用let声明就会报错
// 因为函数变量提升 声明过了 你let又声明一次就会报错
console.log(4);
};
// 函数也会变量提升 不过函数是整体提升上去 var 这是声明而已
// var getName
// getName =getName() { console.log(5); } 后面 var 还有个赋值操作 又覆盖了
// getName =getName() { console.log(4); }
function getName() {
console.log(5);
}
// Foo对象调用自己的getName方法 也就是静态方法
Foo.getName(); //2
// 这里调用 全局(window)的getName方法 函数声明的5 被 var 声明的 4覆盖了
getName(); //4
// new 作用 创建对象 函数里面的this指向这个对象 指向函数 返回这个对象
// 这里没有new 也就是里面的this指向的是 (window)执行这个函数里面的代码,覆盖了上面的 全局的getName方法 4变成了1
Foo().getName(); //1
// 全局都被修改了 getName方法 就是1
getName(); //1
// 这里new 没有作用(构造函数没有被调用) 相当于调用静态方法
new Foo.getName(); //2
// 这里是 new 执行 返回这个对象 这个对象 没有这个方法 就会往原型上面找 Foo.prototype.getName 也就是这个方法 3
new Foo().getName(); //3
// 这里是 new Foo() => {} .getName() => new udf 虽然不会报错但是这个new没有什么作用的
// 你 new new Foo()这样就会报错 说你这个不是一个构造函数说
new new Foo().getName();
// TypeError: (intermediate value) is not a constructor TypeError:(中间值)不是一个构造函数 也就是说你没有这个函数 这个函数是 new时候都会有的
// new Foo() => new {} () 这个{} 也就是中间值不是一个构造函数了
new new Foo()();
// let a = true; true 会转换成为1
// console.log(a == 1 && a == 2 && a == 3);
// console.log(a == 1); //true
// console.log(a == 2); //false
// console.log(a == 3); //false
// 一个对象或者是数组相加,本身是加不了的。就需要进行隐s转换,这里就会调用toSting方法了
// let a = {
// _a: 0,
// toString() {
// return ++this._a;
// },
// };
// if (a == 1 && a == 2 && a == 3) {
// console.log('成功了');
// }
// JS里面直接使用变量,没有声明这个变量就会存在全局里面也就是wd里面
// let _a = 0;
// Object.defineProperty(window, 'a', {
// get() {
// return ++_a;
// },
// });
// if (a === 1 && a === 2 && a === 3) {
// console.log('成功了');
// }
// 这里{}+{}本身就不能直接进行计算,就需要通过转换。进行隐私转换。({}).toString() {}直接调用这个toString是会报错的
// 就需要通过()进行调用,这个本身会 let data = {}并没有什么区别 '[object Object]' + '[object Object]'
let a = ({} + {}).length; //30
// 这里[] + []本身就不能直接进行计算,就需要通过转换。进行隐私转换。数组的toString指的是什么呢?是里面的元素也就是[1,2]这里就是2
let b = ([] + []).length;
let c = function (a, b, c, d) {
console.log(arguments.length);
};
c(1, 2, 3);
// Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
// 0
// :
// 1
// 1
// :
// 2
// 2
// :
// 3
// callee
// :
// ƒ (a, b, c)
// length
// :
// 3
// Symbol(Symbol.iterator)
// :
// ƒ values()
// [[Prototype]]
// :
// Object;
// 普通函数是有 arguments这个属性指的是数组里面都是实参,那么数组的 toString是什么就是里面的元素个数了
// Arguments.callee 就是形参了 实参和形参关系是映射关系,相当于 = 赋值的关系
let d = function (a, b, d, e) {}.length;
console.log(a, b, d);