js用new实例化对象与直接调用的this的区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js用new实例化对象与直接调用的this的区别相关的知识,希望对你有一定的参考价值。
参考技术A function Fun(argument1,argument2)return this;
//直接调用
var f1 = Fun(); // window
//实例化对象
var f2 = new Fun(); // Fun
f1 只是调用 Fun函数,而 f2是实例化对象 Fun。两个的this指向的不是同个地方。调用函数的this指向的是window,实例化对象的this指向的是对象本身。
(构造函数的命名通常使用驼峰命名法,首字母大写,以此和普通的函数区分开来,这是一种习惯用法。)
测试例子:
如上,f只是调用fun1,输出的第一个this是指向window的。fun2也只是调用,所以this也是指向windowde。a是实例化的对象,this指向的是fun3实例化后的对象。
如果做下面调整。
如上,fun1跟fun3是被实例化,this指向对象本身,fun2只是调用,this指向window。
那给this的属性赋值会有什么样的结果呢?
调用函数里面的this属性赋值都是给window赋值的。
如果 fun1()改成 var a = new fun1(); 呢?
大家仔细看看输出的结果。
JS构造函数
构造函数
{ /* 工厂函数通过new运算符改造成了 构造函数; 构造函数: 1.首字母大写; 为了让普通函数和构造函数的区分 2.this指向实例化对象 */ function Person(name,age){ this.num = 0; this.name = name; this.age = age; this.hobby = function(){ console.log("喜欢篮球"); }; } // 调用构造函数: // new : 实例化; let zhangsan = new Person("张三",20); { // 静态属性和方法;(属于类本身) -> 静态成员 // 假如需要统计一下这个构造函数有多少个实例化对象: let zhangsan = new Person("张三",20); // zhangsan.num ++; // console.log(zhangsan.num);//1 let lisi = new Person("李四",21); // lisi.num ++; // console.log(lisi.num);//1 // 可以看到上面有两个实例化对象了,但结果依然还是1; // 所以这个属性就要放到构造函数中当属性; Person.num = 0; Person.fn = function (){ console.log("fn"); }; Person.num ++; Person.num ++; console.log(Person.num);//2 } }
构造函数性能问题
{ // 构造函数性能 function Person(name){ this.name = name; this.age = 20; this.hobby = function(){ console.log("喜欢篮球") } } let zhangsan = new Person("张三"); let lisi = new Person("李四"); console.log(lisi.hobby === zhangsan.hobby);//false -> 对象的比较:不仅要值一样,地址也需要一样 // 在这里可以看到有两个实例化对象,他们在内存里分别保存了同样的内容,占据了一些内存; }
原型
{ // 原型 function Person(name){ this.name = name; this.age = 20; // this.hobby = function(){ // console.log("喜欢篮球") // } } let zhangsan = new Person("张三"); let lisi = new Person("李四"); // 什么是原型呢:每一个构造函数,在实例化的过程中,它都会有两个部分构成:1.构造函数(本身);2.公共空间(原型); Person.prototype.hobby = function(){//方法可以放到原型上面 console.log("喜欢篮球"); } console.log(lisi.hobby === zhangsan.hobby);//true -> 方法放到原型上面之后,不管是实例化多少个对象,他们的方法都是同一个方法,而不是在内存里面新开辟的地址,所以这样就更节约性能 // 原型:1.this指向还是实例化对象 2.每一次声明构造函数的时候prototype都是自动有的 /* 构造函数有两部分:1.本身;2.原型 实例化对象也是有两部分:1.自身属性和方法(也就是构造函数里面的属性和方法); 2.自己的原型(__proto__) */ console.log(zhangsan.__proto__ === Person.prototype);//他们两个是同样一个东西,只是表示形式不一样而已~ // 原型的固有属性; console.log(Person.prototype.constructor === Person);//指向构造函数 console.log(zhangsan.constructor === Person);//true -> 可以用来判断实例化对象是哪个构造函数 // 原型prototype注意点: // 可以追加方法,不要进行覆盖,即使覆盖了,也要把constructor指向构造函数; Person.prototype = { hobby(){ console.log("喜欢篮球") }, constructor:Person } // prototype的constructor的情况:可以判断是否是 数组,对象等系统对象; let arr = [1,2,3]; console.log(arr.constructor === Array);//true let str = "123324"; console.log(str.constructor === String);//true }
构造函数,原型,实例化 三者关系:
// 构造函数,原型,实例化 三者关系: let temp; let temp1; function Person(name){ this.name = name; this.age = 20; temp = this; } Person.prototype.fn = function(){//原型可以加方法 console.log("fn"); temp1 = this; } let zhangsan = new Person("张三");//构造函数可以通过new得到对象 // 这时候: 实例化对象的属性和方法来自构造函数的属性和方法; console.log(zhangsan); // this指向实例化: console.log(zhangsan === temp);//true // prototype 指向实例化对象 zhangsan.fn(); console.log(zhangsan === temp1);//true // constructor指向构造函数 console.log(Person.prototype.constructor === Person);//true
工厂函数与构造函数的对比:
{ // 工厂函数与构造函数的对比: { function Person(name){ let obj = {}; obj.name = name; obj.age = 20; obj.fu = function(){ console.log("fn"); } return obj; } let zhangsan = Person("张三"); } { function Person(name){ this.name = name; this.age = 20; } Person.prototype.fn = function(){ console.log("fn"); } let zhangsan = new Person(); } /* 为什么构造函数比构造函数 使用多: 1.方法在公共空间里面(prototype) 2.创建的对象的指向问题 : 构造函数有constructor */ }
原型链
{ // 原型链 function Foo(name){ this.name = name; this.age = 20; // this.test = "你好"; } //原型: 也是对象 所以也就有__proto__,__proto__也是对象所以也还有原型... Foo.prototype.fn = function(){ console.log("fn"); } // Foo.prototype.test = "原型_你好"; let newFoo = new Foo("张三"); let obj = new Object();//所有的对象都是来自于 Object; Object.prototype.test = "系统原型_你好"; // 所以最终的结果是; console.log(Object.prototype.__proto__); // 那原型链有啥用: 查找规则: 如果构造函数没有,就去原型,一步一步往原型链查找!||假如都有就是 就近原则 console.log(newFoo.test) }
以上是关于js用new实例化对象与直接调用的this的区别的主要内容,如果未能解决你的问题,请参考以下文章
Java基础(42):Java中主类中定义方法加static和不加static的区别(前者可以省略类名直接在祝方法调用,后者必须先实例化后用实例调用)