1.创建对象有以下几种方式:

①.var obj = {};

②.var obj = new Object();

③.自定义构造函数,然后使用构造函数创建对象

 【构造函数和普通函数的区别:函数名遵循大驼峰式命名规则,通常我们使用构造函数创建对象】

2.构造函数内部原理

 ①.在函数体内部隐式的加上 var this = {}【当然这个var this={}实际上是在AO对象中创建的!】

②.执行this.xxx = xxx;

③.隐式的返回this

代码如下所示:

 <script type="text/javascript">
function Student(name,age,sex){
/* var this = {
name:"",
age:
}; */
this.name = name;
this.age = age;
this.sex = sex;
this.grade = 2017; //return this;
} var student = new Student('zhangsan',13,'male');
</script>

【需要特别注意:构造函数需要发现new关键字之后才会有构造函数的上面的三步走原理,否则构造函数就和一个普通的函数一样,没啥区别!】

 <script type="text/javascript">
function Student(name,age,sex){
//var this = {}
this.name = name;
this.age = age;
this.sex = sex;
this.say = function(){
console.log(this.name);
}
//return this
} var student = new Student('zhangsan',13,'male');
student.say(); </script>

而且,一旦我们new一个构造函数来创建对象,那么这个函数不可以返回一个原始值【如果我们返回一个原始值,那么构造函数是会忽略掉这个原始值的,直接返回隐式的this对象】,但是可以返回一个对象、数组等非原始值!

如下代码所示:

 <script type="text/javascript">
function Student(name,age,sex){
//var this = {}
this.name = name;
this.age = age;
this.sex = sex;
this.say = function(){
console.log(this.name);
}
//return this
} var student = new Student('zhangsan',13,'male');
</script>

在控制台上我们输入student,就可以查看该student对象,如下所示:

当然,即使是我们显示的返回this,或者{}、或者一个数组[]等非原始值都是没有问题的,如下所示:

 <script type="text/javascript">
function Student(name,age,sex){
//var this = {}
this.name = name;
this.age = age;
this.sex = sex;
this.say = function(){
console.log(this.name);
}
return ["zhangsan","lisi"];
} var student = new Student('zhangsan',13,'male');
</script>

但是如果我们在构造函数里面返回的是一个原始值,如:123结果就会看到我们在控制台上找student对象的时候并不是显示123,而是显示的隐式this对象的内容,这是因为构造函数是不允许使用原始值作为函数的返回值的,既是是构造函数返回了一个原始值,那么这个原始值也会被忽略,而返回this对象,所以这里有问题,如下所示:

 <script type="text/javascript">
function Student(name,age,sex){
//var this = {}
this.name = name;
this.age = age;
this.sex = sex;
this.say = function(){
console.log(this.name);
}
return 123;
} var student = new Student('zhangsan',13,'male');
</script>

3.包装类

  ①.new String();

②.new Boolean()

③.new Number()

注意:在javascript中有两种数字【123,new Number(123)也即:原始值123、对象123】和两种字符串【原始值""字符串、对象字符串new String()】、以及两种boolean值【原始布尔值true或者false、对象布尔值true或者false】

之所以讲有两种数字和两种字符串是因为原始值字符串和原始值数字是不可以有属性和方法的,而对象数字和对象字符串才是可以有属性和方法的!而且对象数字也是可以直接参与运算的,但是运算完成之后就成了原始值了,就不是对象了!上述对于字符串和布尔值也是适用的!

注意:原始值是不能加属性的,但是如下代码是怎么回事呢?

 <script type="text/javascript">
var str = "hello world";
console.log(str.length);
</script>

不是说原始字符串没有属性和方法么,为啥这里可以打印出str.length的属性值呢?

再来一个:

 <script type="text/javascript">
var num = 4;
num.len = 3;
console.log(num.len);
</script>

不是原始数值不可以加属性么,为什么console.log(num.len)没有错误呢?

以上这两种情况都是由于包装类的原因【切记:原始值是没有属性和方法的!】

实际上上述代码当我们使用num.len=3的时候,实际上js代码会将原始数值转换为:new Number(4).len = 3,并且将这个对象Number删除,即:delete new Number(4),不做其他修改! 然后当我们console.log(num.len)的时候,js非常友善,它又创建了new Number(4)对象,然后在这个对象上面加上len属性,即:new Number(4).len,所以这时候的len属性是undefined!

所以常常有人利用这个来出题:我们都知道数组是可以截串的!例如:

 <script type="text/javascript">
var arr= [1,2,3,4];
console.log(arr);
arr.length = 2;
console.log(arr);
</script>

然后面试官就会问:

 <script type="text/javascript">
var str="Hello World";
console.log(str);
str.length = 2;
console.log(str);
</script>

然后下面的console.log(str)会输出啥呢?很多人就会答错了,实际上这个还是会输出Hello World,,这是要因为当我们在为str赋值属性值的时候,原始字符串会转换成对象字符串new String("Hello World"),然后赋值length属性值为2,就会产生一个截串,之后就将这个字符串对象给删除,当我们再次访问console.log(str)的时候,就会输出原来的"Hello World"字符串!而且我们也可以再次输出str.length属性验证,值应该为11,而不是2,当然这个str.length实际上是new String("Hello World").length值为11;

 <script type="text/javascript">
var str="Hello World";
console.log(str);
str.length = 2;
console.log(str);
console.log(str.length);
</script>

再来一道测试题,如下所示:

 <script type="text/javascript">
var str = "abc";
str +=1;
var test = typeof(str);
if(test.length == 6){
test.sign = "typeof的返回结果可能为String类型";
}
console.log(test.sign);
</script>

显然test.sign在if语句里面是能赋值的,但是test.sign赋值是new String(test变量代表的值).sign赋的值,赋值完之后又删除了new String(test变量代表的值)这个对象,所以到下面if语句之外我们再打印console.log(test.sign)的时候,打印的结果是undefined;

5.原型

①.定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。

 ②.利用原型特点和概念,可以提取共有属性。

③.对象如何查看原型------>隐式属性 __proto__

④.对象如何查看对象的构造函数----->Constructor

注意:原型实际上就是继承的关系;代码如下所示:

 <script type="text/javascript">
//Person.prototype --原型
//Person..prototype = {} 是祖先
Person.prototype.name = "hehe";
function Person(){ }
var person = new Person();
console.log(person);
</script>

输出的结果如下所示:

再例如:

 <script type="text/javascript">
//Person.prototype --原型
//Person..prototype = {} 是祖先
Person.prototype.name = "hehe";
Person.prototype.say = function(){
console.log('hehe');
}
function Person(){ }
var person = new Person();
person.say();
</script>

当然,函数的对象也可以有自己的属性,当自己的属性和继承的原型的属性重叠时,以自己的属性为主,如下所示:

 <script type="text/javascript">
//Person.prototype --原型
//Person..prototype = {} 是祖先
Person.prototype.name = "hehe";
Person.prototype.address = "山东";
Person.prototype.say = function(){
console.log('hehe');
}
function Person(name,age,gender){
this.name = name;
this.age = age;
this.gender =gender;
}
var person = new Person('zhangsan',12,'male');
console.log(person);
</script>

结果如下所示:

注意:一般情况下,我们可以将子类对象的公共的属性提取到其对应的父类中,那么这里原型就是最好的父类,所以我们可以将子类公共属性都提取到原型中,但是我们在原型中如果设置了某个属性,那么函数的每个对象都会继承原型的属性,但是如果我们修改了某个对象的属性【从原型中继承过来的】,那么这仅仅是修改的某个对象本身的属性而不是修改的原型中的属性,代码如下所示:

 <script type="text/javascript">
Person.prototype.lastName = 'Deng';
function Person(name){
this.name = name;
}
var person = new Person('xuming');
var person1 = new Person('lisi');
person.lastName="张三";
console.log(person);
console.log(person1);
</script>

你会看到我们修改了xuming的lastName值,但是输出的时候lisi的lastName值并没有修改,也就是原型的lastName值并没有修改!

注意:Person的prototype属性也是一个对象,如下代码:

 <script type="text/javascript">
Person.prototype.lastName = 'Deng';
function Person(name){
this.name = name;
} console.log(Person.prototype); </script>

在控制台上打印输出:

注意:我们上面是通过Person.prototype输出的函数的原型,而且我们这里绝对不能使用函数对象的prototype获取原型,如:我们不能

通过 var person = new Person('张三');person.prototype这样的属性来获取Person函数【类】的原型!

注意:我们可以使用delete删除一个对象的属性,如下所示:

 <script type="text/javascript">
Person.prototype.lastName = 'Deng';
function Person(name){
this.name = name;
} var person = new Person('zhaoliu');
delete person.name;
console.log(person.name);
</script>

结果为:

这样是没问题的,但是如果我们使用的是delete person.lastName,然后再打印输出,你看看是否能删除,

 <script type="text/javascript">
Person.prototype.lastName = 'Deng';
function Person(name){
this.name = name;
} var person = new Person('zhaoliu');
delete person.lastName;
console.log(person.lastName);
</script>

结果为:

你会发现,这是删除不了的,因为js中对象只能删除自己的属性,不是自己的属性,js对象是删除不了的!

而且如果js代码如下所示:

 <script type="text/javascript">
Person.prototype.lastName = 'Deng';
function Person(name){
this.name = name;
} var person = new Person('zhaoliu');
</script>

在控制台上我们先删除对象的name属性值,然后在控制台上打印person.name的值的时候,发现:

对象的name属性值是可以被删除的,而且删除的时候返回了true;

如果我们在控制台上使用的是:

就会发现删除person.lastName的时候返回的是true,但是我们在下面却可以直接通过person.lastName再次查看person对象从原型继承过来的属性,也就是实际上person对象只能删除自身的属性,不能删除原型的属性,而且当我们删除对象的一个不存在的属性的时候,也是会返回true的,如下所示:

如果我们的代码如下所示:

 <script type="text/javascript">
function Car(){ }
var car = new Car(); </script>

那么我们可以使用car.constructor来查看构造car对象的构造函数,如下所示:

这个不是car对象,所以肯定是继承过来的,那是继承的谁的呢,答案是:肯定是继承的Car的原型对象的,我们可以在控制台上打印看一下,如下所示:

这就更加证实了,这是Car类的原型的自带的构造函数!

JS构造函数原理与原型的更多相关文章

  1. js 构造函数(construction)与原型(prototype)

    1.面向对象:js原型 java有class和instance,js仅仅有构造函数(function Cat(name,age){this.name=name;this.age=age}),为了实现数 ...

  2. 深入研究js构造函数和原型

    很快就要从新浪离职了,最近心情比较轻松,抽点空整理一下构造函数和原型的机理. 我们都知道,在经典设计模式中我们最常用的就是工厂模式.构造函数模式.原型模式这几种,听起来‘模式’好像很高大上的样子,实际 ...

  3. JS构造函数的用法和JS原型

    $(function(){ var rec = new Rectangle(5, 10); //alert(rec.width + "*" + rec.height + " ...

  4. 面向对象JS基础讲解,工厂模式、构造函数模式、原型模式、混合模式、动态原型模式

    什么是面向对象?面向对象是一种思想!(废话). 面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法.这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.接下 ...

  5. 关于js的对象创建方法(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)

    // 1.工厂方式创建对象:面向对象中的封装函数(内置对象) 简单来说就是封装后的代码,简单的工厂模式是很好理解的,关于它的作用,就是利用面向对象的方法,把一些对象封装,使一些占用空间多的,重复的代码 ...

  6. js面向对象、创建对象的工厂模式、构造函数模式、原型链模式

    JS面向对象编程(转载) 什么是面向对象编程(OOP)?用对象的思想去写代码,就是面向对象编程. 面向对象编程的特点 抽象:抓住核心问题 封装:只能通过对象来访问方法 继承:从已有对象上继承出新的对象 ...

  7. 笔记: js构造函数与原型

    目录 构造函数与原型介绍 涉及三种引用的操作 有关原型及原型链的一些相关方法总结 @ 构造函数与原型介绍 1.函数与函数的原型对象(prototype object): 在JavaScript中,创建 ...

  8. js设计模式:工厂模式、构造函数模式、原型模式、混合模式

    一.js面向对象程序 var o1 = new Object();     o1.name = "宾宾";     o1.sex = "男";     o1.a ...

  9. JS面向对象基础讲解(工厂模式、构造函数模式、原型模式、混合模式、动态原型模式)

    什么是面向对象?面向对象是一种思想. 面向对象可以把程序中的关键模块都视为对象, 而模块拥有属性及方法. 这样如果我们把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作.   工厂 ...

随机推荐

  1. 深度讲解 .net session 过期机制

    [参考]net session过期 原理及解决办法 [参考]深入理解session过期机制

  2. apache2.4 httpd.conf httpd-vhost.conf配置

    extra / httpd-vhost.conf <VirtualHost *:81> DocumentRoot "/data/sda1_data/" ServerNa ...

  3. 真正让HTML标签、DIV、SPAN拥有onfocus和onblur,聚焦和失焦

    转载:http://blog.sina.com.cn/s/blog_7dfe67db01010lnq.html 默认火狐或者其他浏览器里DIV和其他普通标签是不具有onfocus和onblur事件的, ...

  4. 【GIS】无人机相关技术(转)

    ---------------------------------------------------------------------------------------------------G ...

  5. pom.xml文件最详细的讲解

    1 引入额外的jar包 <dependency> <groupId>bitwalker</groupId> <artifactId>UserAgentU ...

  6. C#获取一个数组中的最大值、最小值、平均值

    C#获取一个数组中的最大值.最小值.平均值 1.给出一个数组 ,,,,,-,,,,}; 2.数组Array自带方法 本身是直接可以调用Min(),Max(),Average()方法来求出 最小值.最大 ...

  7. JPA唯一索引更新删除的问题

    本来的功能是更新,我的做法是先删除再新增.表设置了字段A和字段B的唯一主键,先删除这个字段再新增一一模一样的值(包含字段A和字段B)时会报唯一主键的值重复了,百度了下,没找到原因,于是就不删除记录了, ...

  8. 11.2vue(3)

    2018-11-2 19:00:33 明天周末,又可以愉快整理博客啦! 越努力,越幸运!永远不要高估自己!!! 接着学vue 感觉好强大! 用这个组件的好处就是,不需要手动刷新,文件只要把保存就自动刷 ...

  9. 用memset设置无穷大无穷小

    memeset是以字节为单位进行赋值的,对字符数组可以直接用. 但对于int数组就不行了. 但设置无穷大来说有个技巧: 如果我们将无穷大设为0x3f3f3f3f,那么奇迹就发生了,0x3f3f3f3f ...

  10. Linux 的基本操作(系统的远程登录)

    系统的远程登录 首先要说一下,该部分内容对于linux初学者来讲并不是特别重要的,可以先跳过该章节,先学下一章,等学完后再回来看这一章. Linux大多应用于服务器,而服务器不可能像PC一样放在办公室 ...